+++ /dev/null
-#ifndef __NET_PKT_SCHED_H
-#define __NET_PKT_SCHED_H
-
-#define PSCHED_GETTIMEOFDAY 1
-#define PSCHED_JIFFIES 2
-#define PSCHED_CPU 3
-
-#define PSCHED_CLOCK_SOURCE PSCHED_JIFFIES
-
-#include <linux/config.h>
-#include <linux/pkt_sched.h>
-//#include <net/pkt_cls.h>
-
-#ifdef CONFIG_X86_TSC
-#include <asm/msr.h>
-#endif
-
-struct rtattr;
-struct Qdisc;
-
-struct qdisc_walker
-{
- int stop;
- int skip;
- int count;
- int (*fn)(struct Qdisc *, unsigned long cl, struct qdisc_walker *);
-};
-
-struct Qdisc_class_ops
-{
- /* Child qdisc manipulation */
- int (*graft)(struct Qdisc *, unsigned long cl, struct Qdisc *, struct Qdisc **);
- struct Qdisc * (*leaf)(struct Qdisc *, unsigned long cl);
-
- /* Class manipulation routines */
- unsigned long (*get)(struct Qdisc *, u32 classid);
- void (*put)(struct Qdisc *, unsigned long);
- int (*change)(struct Qdisc *, u32, u32, struct rtattr **, unsigned long *);
- int (*delete)(struct Qdisc *, unsigned long);
- void (*walk)(struct Qdisc *, struct qdisc_walker * arg);
-
-#if 0
- /* Filter manipulation */
- struct tcf_proto ** (*tcf_chain)(struct Qdisc *, unsigned long);
- unsigned long (*bind_tcf)(struct Qdisc *, unsigned long, u32 classid);
- void (*unbind_tcf)(struct Qdisc *, unsigned long);
-#endif
-};
-
-struct Qdisc_ops
-{
- struct Qdisc_ops *next;
- struct Qdisc_class_ops *cl_ops;
- char id[IFNAMSIZ];
- int priv_size;
-
- int (*enqueue)(struct sk_buff *, struct Qdisc *);
- struct sk_buff * (*dequeue)(struct Qdisc *);
- int (*requeue)(struct sk_buff *, struct Qdisc *);
- int (*drop)(struct Qdisc *);
-
- int (*init)(struct Qdisc *, struct rtattr *arg);
- void (*reset)(struct Qdisc *);
- void (*destroy)(struct Qdisc *);
- int (*change)(struct Qdisc *, struct rtattr *arg);
-
- int (*dump)(struct Qdisc *, struct sk_buff *);
-};
-
-extern rwlock_t qdisc_tree_lock;
-
-struct Qdisc
-{
- int (*enqueue)(struct sk_buff *skb, struct Qdisc *dev);
- struct sk_buff * (*dequeue)(struct Qdisc *dev);
- unsigned flags;
-#define TCQ_F_BUILTIN 1
-#define TCQ_F_THROTTLED 2
-#define TCQ_F_INGRES 4
- struct Qdisc_ops *ops;
- struct Qdisc *next;
- u32 handle;
- atomic_t refcnt;
- struct sk_buff_head q;
- struct net_device *dev;
-
- //struct tc_stats stats;
- int (*reshape_fail)(struct sk_buff *skb, struct Qdisc *q);
-
- /* This field is deprecated, but it is still used by CBQ
- * and it will live until better solution will be invented.
- */
- struct Qdisc *__parent;
-
- char data[0];
-};
-
-struct qdisc_rate_table
-{
- //struct tc_ratespec rate;
- u32 data[256];
- struct qdisc_rate_table *next;
- int refcnt;
-};
-
-static inline void sch_tree_lock(struct Qdisc *q)
-{
- write_lock(&qdisc_tree_lock);
- spin_lock_bh(&q->dev->queue_lock);
-}
-
-static inline void sch_tree_unlock(struct Qdisc *q)
-{
- spin_unlock_bh(&q->dev->queue_lock);
- write_unlock(&qdisc_tree_lock);
-}
-
-#if 0
-static inline void tcf_tree_lock(struct tcf_proto *tp)
-{
- write_lock(&qdisc_tree_lock);
- spin_lock_bh(&tp->q->dev->queue_lock);
-}
-
-static inline void tcf_tree_unlock(struct tcf_proto *tp)
-{
- spin_unlock_bh(&tp->q->dev->queue_lock);
- write_unlock(&qdisc_tree_lock);
-}
-
-static inline unsigned long
-cls_set_class(struct tcf_proto *tp, unsigned long *clp, unsigned long cl)
-{
- unsigned long old_cl;
-
- tcf_tree_lock(tp);
- old_cl = *clp;
- *clp = cl;
- tcf_tree_unlock(tp);
- return old_cl;
-}
-
-static inline unsigned long
-__cls_set_class(unsigned long *clp, unsigned long cl)
-{
- unsigned long old_cl;
-
- old_cl = *clp;
- *clp = cl;
- return old_cl;
-}
-#endif
-
-
-/*
- Timer resolution MUST BE < 10% of min_schedulable_packet_size/bandwidth
-
- Normal IP packet size ~ 512byte, hence:
-
- 0.5Kbyte/1Mbyte/sec = 0.5msec, so that we need 50usec timer for
- 10Mbit ethernet.
-
- 10msec resolution -> <50Kbit/sec.
-
- The result: [34]86 is not good choice for QoS router :-(
-
- The things are not so bad, because we may use artifical
- clock evaluated by integration of network data flow
- in the most critical places.
-
- Note: we do not use fastgettimeofday.
- The reason is that, when it is not the same thing as
- gettimeofday, it returns invalid timestamp, which is
- not updated, when net_bh is active.
-
- So, use PSCHED_CLOCK_SOURCE = PSCHED_CPU on alpha and pentiums
- with rtdsc. And PSCHED_JIFFIES on all other architectures, including [34]86
- and pentiums without rtdsc.
- You can use PSCHED_GETTIMEOFDAY on another architectures,
- which have fast and precise clock source, but it is too expensive.
- */
-
-/* General note about internal clock.
-
- Any clock source returns time intervals, measured in units
- close to 1usec. With source PSCHED_GETTIMEOFDAY it is precisely
- microseconds, otherwise something close but different chosen to minimize
- arithmetic cost. Ratio usec/internal untis in form nominator/denominator
- may be read from /proc/net/psched.
- */
-
-
-#if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY
-
-typedef struct timeval psched_time_t;
-typedef long psched_tdiff_t;
-
-#define PSCHED_GET_TIME(stamp) do_gettimeofday(&(stamp))
-#define PSCHED_US2JIFFIE(usecs) (((usecs)+(1000000/HZ-1))/(1000000/HZ))
-
-#define PSCHED_EXPORTLIST EXPORT_SYMBOL(psched_tod_diff);
-
-#else /* PSCHED_CLOCK_SOURCE != PSCHED_GETTIMEOFDAY */
-
-#define PSCHED_EXPORTLIST PSCHED_EXPORTLIST_1 PSCHED_EXPORTLIST_2
-
-typedef u64 psched_time_t;
-typedef long psched_tdiff_t;
-
-extern psched_time_t psched_time_base;
-
-#if PSCHED_CLOCK_SOURCE == PSCHED_JIFFIES
-
-#if HZ == 100
-#define PSCHED_JSCALE 13
-#elif HZ == 1024
-#define PSCHED_JSCALE 10
-#else
-#define PSCHED_JSCALE 0
-#endif
-
-#define PSCHED_EXPORTLIST_2
-
-#if ~0UL == 0xFFFFFFFF
-
-#define PSCHED_WATCHER unsigned long
-
-extern PSCHED_WATCHER psched_time_mark;
-
-#define PSCHED_GET_TIME(stamp) ((stamp) = psched_time_base + (((unsigned long)(jiffies-psched_time_mark))<<PSCHED_JSCALE))
-
-#define PSCHED_EXPORTLIST_1 EXPORT_SYMBOL(psched_time_base); \
- EXPORT_SYMBOL(psched_time_mark);
-
-#else
-
-#define PSCHED_GET_TIME(stamp) ((stamp) = (jiffies<<PSCHED_JSCALE))
-
-#define PSCHED_EXPORTLIST_1
-
-#endif
-
-#define PSCHED_US2JIFFIE(delay) (((delay)+(1<<PSCHED_JSCALE)-1)>>PSCHED_JSCALE)
-
-#elif PSCHED_CLOCK_SOURCE == PSCHED_CPU
-
-extern psched_tdiff_t psched_clock_per_hz;
-extern int psched_clock_scale;
-
-#define PSCHED_EXPORTLIST_2 EXPORT_SYMBOL(psched_clock_per_hz); \
- EXPORT_SYMBOL(psched_clock_scale);
-
-#define PSCHED_US2JIFFIE(delay) (((delay)+psched_clock_per_hz-1)/psched_clock_per_hz)
-
-#ifdef CONFIG_X86_TSC
-
-#define PSCHED_GET_TIME(stamp) \
-({ u64 __cur; \
- rdtscll(__cur); \
- (stamp) = __cur>>psched_clock_scale; \
-})
-
-#define PSCHED_EXPORTLIST_1
-
-#elif defined (__alpha__)
-
-#define PSCHED_WATCHER u32
-
-extern PSCHED_WATCHER psched_time_mark;
-
-#define PSCHED_GET_TIME(stamp) \
-({ u32 __res; \
- __asm__ __volatile__ ("rpcc %0" : "r="(__res)); \
- if (__res <= psched_time_mark) psched_time_base += 0x100000000UL; \
- psched_time_mark = __res; \
- (stamp) = (psched_time_base + __res)>>psched_clock_scale; \
-})
-
-#define PSCHED_EXPORTLIST_1 EXPORT_SYMBOL(psched_time_base); \
- EXPORT_SYMBOL(psched_time_mark);
-
-#else
-
-#error PSCHED_CLOCK_SOURCE=PSCHED_CPU is not supported on this arch.
-
-#endif /* ARCH */
-
-#endif /* PSCHED_CLOCK_SOURCE == PSCHED_JIFFIES */
-
-#endif /* PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY */
-
-#if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY
-#define PSCHED_TDIFF(tv1, tv2) \
-({ \
- int __delta_sec = (tv1).tv_sec - (tv2).tv_sec; \
- int __delta = (tv1).tv_usec - (tv2).tv_usec; \
- if (__delta_sec) { \
- switch (__delta_sec) { \
- default: \
- __delta = 0; \
- case 2: \
- __delta += 1000000; \
- case 1: \
- __delta += 1000000; \
- } \
- } \
- __delta; \
-})
-
-extern int psched_tod_diff(int delta_sec, int bound);
-
-#define PSCHED_TDIFF_SAFE(tv1, tv2, bound, guard) \
-({ \
- int __delta_sec = (tv1).tv_sec - (tv2).tv_sec; \
- int __delta = (tv1).tv_usec - (tv2).tv_usec; \
- switch (__delta_sec) { \
- default: \
- __delta = psched_tod_diff(__delta_sec, bound); guard; break; \
- case 2: \
- __delta += 1000000; \
- case 1: \
- __delta += 1000000; \
- case 0: ; \
- } \
- __delta; \
-})
-
-#define PSCHED_TLESS(tv1, tv2) (((tv1).tv_usec < (tv2).tv_usec && \
- (tv1).tv_sec <= (tv2).tv_sec) || \
- (tv1).tv_sec < (tv2).tv_sec)
-
-#define PSCHED_TADD2(tv, delta, tv_res) \
-({ \
- int __delta = (tv).tv_usec + (delta); \
- (tv_res).tv_sec = (tv).tv_sec; \
- if (__delta > 1000000) { (tv_res).tv_sec++; __delta -= 1000000; } \
- (tv_res).tv_usec = __delta; \
-})
-
-#define PSCHED_TADD(tv, delta) \
-({ \
- (tv).tv_usec += (delta); \
- if ((tv).tv_usec > 1000000) { (tv).tv_sec++; \
- (tv).tv_usec -= 1000000; } \
-})
-
-/* Set/check that time is in the "past perfect";
- it depends on concrete representation of system time
- */
-
-#define PSCHED_SET_PASTPERFECT(t) ((t).tv_sec = 0)
-#define PSCHED_IS_PASTPERFECT(t) ((t).tv_sec == 0)
-
-#define PSCHED_AUDIT_TDIFF(t) ({ if ((t) > 2000000) (t) = 2000000; })
-
-#else
-
-#define PSCHED_TDIFF(tv1, tv2) (long)((tv1) - (tv2))
-#define PSCHED_TDIFF_SAFE(tv1, tv2, bound, guard) \
-({ \
- long __delta = (tv1) - (tv2); \
- if ( __delta > (bound)) { __delta = (bound); guard; } \
- __delta; \
-})
-
-
-#define PSCHED_TLESS(tv1, tv2) ((tv1) < (tv2))
-#define PSCHED_TADD2(tv, delta, tv_res) ((tv_res) = (tv) + (delta))
-#define PSCHED_TADD(tv, delta) ((tv) += (delta))
-#define PSCHED_SET_PASTPERFECT(t) ((t) = 0)
-#define PSCHED_IS_PASTPERFECT(t) ((t) == 0)
-#define PSCHED_AUDIT_TDIFF(t)
-
-#endif
-
-struct tcf_police
-{
- struct tcf_police *next;
- int refcnt;
- u32 index;
-
- int action;
- int result;
- u32 ewma_rate;
- u32 burst;
- u32 mtu;
-
- u32 toks;
- u32 ptoks;
- psched_time_t t_c;
- spinlock_t lock;
- struct qdisc_rate_table *R_tab;
- struct qdisc_rate_table *P_tab;
-
- //struct tc_stats stats;
-};
-
-//extern int qdisc_copy_stats(struct sk_buff *skb, struct tc_stats *st);
-extern void tcf_police_destroy(struct tcf_police *p);
-extern struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est);
-extern int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p);
-extern int tcf_police(struct sk_buff *skb, struct tcf_police *p);
-
-static inline void tcf_police_release(struct tcf_police *p)
-{
- if (p && --p->refcnt == 0)
- tcf_police_destroy(p);
-}
-
-extern struct Qdisc noop_qdisc;
-extern struct Qdisc_ops noop_qdisc_ops;
-extern struct Qdisc_ops pfifo_qdisc_ops;
-extern struct Qdisc_ops bfifo_qdisc_ops;
-
-int register_qdisc(struct Qdisc_ops *qops);
-int unregister_qdisc(struct Qdisc_ops *qops);
-struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
-struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle);
-void dev_init_scheduler(struct net_device *dev);
-void dev_shutdown(struct net_device *dev);
-void dev_activate(struct net_device *dev);
-void dev_deactivate(struct net_device *dev);
-void qdisc_reset(struct Qdisc *qdisc);
-void qdisc_destroy(struct Qdisc *qdisc);
-struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops);
-//int qdisc_new_estimator(struct tc_stats *stats, struct rtattr *opt);
-//void qdisc_kill_estimator(struct tc_stats *stats);
-//struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct rtattr *tab);
-void qdisc_put_rtab(struct qdisc_rate_table *tab);
-int teql_init(void);
-int tc_filter_init(void);
-int pktsched_init(void);
-
-extern int qdisc_restart(struct net_device *dev);
-
-static inline void qdisc_run(struct net_device *dev)
-{
- while (!netif_queue_stopped(dev) &&
- qdisc_restart(dev)<0)
- /* NOTHING */;
-}
-
-/* Calculate maximal size of packet seen by hard_start_xmit
- routine of this device.
- */
-static inline unsigned psched_mtu(struct net_device *dev)
-{
- unsigned mtu = dev->mtu;
- return dev->hard_header ? mtu + dev->hard_header_len : mtu;
-}
-
-
-/******************************************************************************
- * XXXXXXXXX Rest of this file is real linux/pkt_sched.h XXXXX
- */
-
-
-/* Logical priority bands not depending on specific packet scheduler.
- Every scheduler will map them to real traffic classes, if it has
- no more precise mechanism to classify packets.
-
- These numbers have no special meaning, though their coincidence
- with obsolete IPv6 values is not occasional :-). New IPv6 drafts
- preferred full anarchy inspired by diffserv group.
-
- Note: TC_PRIO_BESTEFFORT does not mean that it is the most unhappy
- class, actually, as rule it will be handled with more care than
- filler or even bulk.
- */
-
-#define TC_PRIO_BESTEFFORT 0
-#define TC_PRIO_FILLER 1
-#define TC_PRIO_BULK 2
-#define TC_PRIO_INTERACTIVE_BULK 4
-#define TC_PRIO_INTERACTIVE 6
-#define TC_PRIO_CONTROL 7
-
-#define TC_PRIO_MAX 15
-
-/* Generic queue statistics, available for all the elements.
- Particular schedulers may have also their private records.
- */
-
-struct tc_stats
-{
- __u64 bytes; /* NUmber of enqueues bytes */
- __u32 packets; /* Number of enqueued packets */
- __u32 drops; /* Packets dropped because of lack of resources */
- __u32 overlimits; /* Number of throttle events when this
- * flow goes out of allocated bandwidth */
- __u32 bps; /* Current flow byte rate */
- __u32 pps; /* Current flow packet rate */
- __u32 qlen;
- __u32 backlog;
-#ifdef __KERNEL__
- spinlock_t *lock;
-#endif
-};
-
-struct tc_estimator
-{
- char interval;
- unsigned char ewma_log;
-};
-
-/* "Handles"
- ---------
-
- All the traffic control objects have 32bit identifiers, or "handles".
-
- They can be considered as opaque numbers from user API viewpoint,
- but actually they always consist of two fields: major and
- minor numbers, which are interpreted by kernel specially,
- that may be used by applications, though not recommended.
-
- F.e. qdisc handles always have minor number equal to zero,
- classes (or flows) have major equal to parent qdisc major, and
- minor uniquely identifying class inside qdisc.
-
- Macros to manipulate handles:
- */
-
-#define TC_H_MAJ_MASK (0xFFFF0000U)
-#define TC_H_MIN_MASK (0x0000FFFFU)
-#define TC_H_MAJ(h) ((h)&TC_H_MAJ_MASK)
-#define TC_H_MIN(h) ((h)&TC_H_MIN_MASK)
-#define TC_H_MAKE(maj,min) (((maj)&TC_H_MAJ_MASK)|((min)&TC_H_MIN_MASK))
-
-#define TC_H_UNSPEC (0U)
-#define TC_H_ROOT (0xFFFFFFFFU)
-#define TC_H_INGRESS (0xFFFFFFF1U)
-
-struct tc_ratespec
-{
- unsigned char cell_log;
- unsigned char __reserved;
- unsigned short feature;
- short addend;
- unsigned short mpu;
- __u32 rate;
-};
-
-/* FIFO section */
-
-struct tc_fifo_qopt
-{
- __u32 limit; /* Queue length: bytes for bfifo, packets for pfifo */
-};
-
-/* PRIO section */
-
-#define TCQ_PRIO_BANDS 16
-
-struct tc_prio_qopt
-{
- int bands; /* Number of bands */
- __u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */
-};
-
-/* CSZ section */
-
-struct tc_csz_qopt
-{
- int flows; /* Maximal number of guaranteed flows */
- unsigned char R_log; /* Fixed point position for round number */
- unsigned char delta_log; /* Log of maximal managed time interval */
- __u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> CSZ band */
-};
-
-struct tc_csz_copt
-{
- struct tc_ratespec slice;
- struct tc_ratespec rate;
- struct tc_ratespec peakrate;
- __u32 limit;
- __u32 buffer;
- __u32 mtu;
-};
-
-enum
-{
- TCA_CSZ_UNSPEC,
- TCA_CSZ_PARMS,
- TCA_CSZ_RTAB,
- TCA_CSZ_PTAB,
-};
-
-/* TBF section */
-
-struct tc_tbf_qopt
-{
- struct tc_ratespec rate;
- struct tc_ratespec peakrate;
- __u32 limit;
- __u32 buffer;
- __u32 mtu;
-};
-
-enum
-{
- TCA_TBF_UNSPEC,
- TCA_TBF_PARMS,
- TCA_TBF_RTAB,
- TCA_TBF_PTAB,
-};
-
-
-/* TEQL section */
-
-/* TEQL does not require any parameters */
-
-/* SFQ section */
-
-struct tc_sfq_qopt
-{
- unsigned quantum; /* Bytes per round allocated to flow */
- int perturb_period; /* Period of hash perturbation */
- __u32 limit; /* Maximal packets in queue */
- unsigned divisor; /* Hash divisor */
- unsigned flows; /* Maximal number of flows */
-};
-
-/*
- * NOTE: limit, divisor and flows are hardwired to code at the moment.
- *
- * limit=flows=128, divisor=1024;
- *
- * The only reason for this is efficiency, it is possible
- * to change these parameters in compile time.
- */
-
-/* RED section */
-
-enum
-{
- TCA_RED_UNSPEC,
- TCA_RED_PARMS,
- TCA_RED_STAB,
-};
-
-struct tc_red_qopt
-{
- __u32 limit; /* HARD maximal queue length (bytes) */
- __u32 qth_min; /* Min average length threshold (bytes) */
- __u32 qth_max; /* Max average length threshold (bytes) */
- unsigned char Wlog; /* log(W) */
- unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
- unsigned char Scell_log; /* cell size for idle damping */
- unsigned char flags;
-#define TC_RED_ECN 1
-};
-
-struct tc_red_xstats
-{
- __u32 early; /* Early drops */
- __u32 pdrop; /* Drops due to queue limits */
- __u32 other; /* Drops due to drop() calls */
- __u32 marked; /* Marked packets */
-};
-
-/* GRED section */
-
-#define MAX_DPs 16
-
-enum
-{
- TCA_GRED_UNSPEC,
- TCA_GRED_PARMS,
- TCA_GRED_STAB,
- TCA_GRED_DPS,
-};
-
-#define TCA_SET_OFF TCA_GRED_PARMS
-struct tc_gred_qopt
-{
- __u32 limit; /* HARD maximal queue length (bytes)
-*/
- __u32 qth_min; /* Min average length threshold (bytes)
-*/
- __u32 qth_max; /* Max average length threshold (bytes)
-*/
- __u32 DP; /* upto 2^32 DPs */
- __u32 backlog;
- __u32 qave;
- __u32 forced;
- __u32 early;
- __u32 other;
- __u32 pdrop;
-
- unsigned char Wlog; /* log(W) */
- unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
- unsigned char Scell_log; /* cell size for idle damping */
- __u8 prio; /* prio of this VQ */
- __u32 packets;
- __u32 bytesin;
-};
-/* gred setup */
-struct tc_gred_sopt
-{
- __u32 DPs;
- __u32 def_DP;
- __u8 grio;
-};
-
-/* CBQ section */
-
-#define TC_CBQ_MAXPRIO 8
-#define TC_CBQ_MAXLEVEL 8
-#define TC_CBQ_DEF_EWMA 5
-
-struct tc_cbq_lssopt
-{
- unsigned char change;
- unsigned char flags;
-#define TCF_CBQ_LSS_BOUNDED 1
-#define TCF_CBQ_LSS_ISOLATED 2
- unsigned char ewma_log;
- unsigned char level;
-#define TCF_CBQ_LSS_FLAGS 1
-#define TCF_CBQ_LSS_EWMA 2
-#define TCF_CBQ_LSS_MAXIDLE 4
-#define TCF_CBQ_LSS_MINIDLE 8
-#define TCF_CBQ_LSS_OFFTIME 0x10
-#define TCF_CBQ_LSS_AVPKT 0x20
- __u32 maxidle;
- __u32 minidle;
- __u32 offtime;
- __u32 avpkt;
-};
-
-struct tc_cbq_wrropt
-{
- unsigned char flags;
- unsigned char priority;
- unsigned char cpriority;
- unsigned char __reserved;
- __u32 allot;
- __u32 weight;
-};
-
-struct tc_cbq_ovl
-{
- unsigned char strategy;
-#define TC_CBQ_OVL_CLASSIC 0
-#define TC_CBQ_OVL_DELAY 1
-#define TC_CBQ_OVL_LOWPRIO 2
-#define TC_CBQ_OVL_DROP 3
-#define TC_CBQ_OVL_RCLASSIC 4
- unsigned char priority2;
- __u32 penalty;
-};
-
-struct tc_cbq_police
-{
- unsigned char police;
- unsigned char __res1;
- unsigned short __res2;
-};
-
-struct tc_cbq_fopt
-{
- __u32 split;
- __u32 defmap;
- __u32 defchange;
-};
-
-struct tc_cbq_xstats
-{
- __u32 borrows;
- __u32 overactions;
- __s32 avgidle;
- __s32 undertime;
-};
-
-enum
-{
- TCA_CBQ_UNSPEC,
- TCA_CBQ_LSSOPT,
- TCA_CBQ_WRROPT,
- TCA_CBQ_FOPT,
- TCA_CBQ_OVL_STRATEGY,
- TCA_CBQ_RATE,
- TCA_CBQ_RTAB,
- TCA_CBQ_POLICE,
-};
-
-#define TCA_CBQ_MAX TCA_CBQ_POLICE
-
-/* dsmark section */
-
-enum {
- TCA_DSMARK_UNSPEC,
- TCA_DSMARK_INDICES,
- TCA_DSMARK_DEFAULT_INDEX,
- TCA_DSMARK_SET_TC_INDEX,
- TCA_DSMARK_MASK,
- TCA_DSMARK_VALUE
-};
-
-#define TCA_DSMARK_MAX TCA_DSMARK_VALUE
-
-/* ATM section */
-
-enum {
- TCA_ATM_UNSPEC,
- TCA_ATM_FD, /* file/socket descriptor */
- TCA_ATM_PTR, /* pointer to descriptor - later */
- TCA_ATM_HDR, /* LL header */
- TCA_ATM_EXCESS, /* excess traffic class (0 for CLP) */
- TCA_ATM_ADDR, /* PVC address (for output only) */
- TCA_ATM_STATE /* VC state (ATM_VS_*; for output only) */
-};
-
-#define TCA_ATM_MAX TCA_ATM_STATE
-
-#endif
#include <linux/brlock.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/pkt_sched.h>
#include <linux/event.h>
#include <asm/domain_page.h>
struct softnet_data softnet_data[NR_CPUS] __cacheline_aligned;
-/*********************************************************************************
-
- Device Interface Subroutines
-
-**********************************************************************************/
-
/**
* __dev_get_by_name - find a device by its name
* @name: name to find
struct net_device *__dev_get_by_name(const char *name)
{
- struct net_device *dev;
+ struct net_device *dev;
- for (dev = dev_base; dev != NULL; dev = dev->next) {
- if (strncmp(dev->name, name, IFNAMSIZ) == 0)
- return dev;
- }
- return NULL;
+ for (dev = dev_base; dev != NULL; dev = dev->next) {
+ if (strncmp(dev->name, name, IFNAMSIZ) == 0)
+ return dev;
+ }
+ return NULL;
}
/**
struct net_device *dev_get_by_name(const char *name)
{
- struct net_device *dev;
-
- read_lock(&dev_base_lock);
- dev = __dev_get_by_name(name);
- if (dev)
- dev_hold(dev);
- read_unlock(&dev_base_lock);
- return dev;
+ struct net_device *dev;
+
+ read_lock(&dev_base_lock);
+ dev = __dev_get_by_name(name);
+ if (dev)
+ dev_hold(dev);
+ read_unlock(&dev_base_lock);
+ return dev;
}
/*
int dev_get(const char *name)
{
- struct net_device *dev;
+ struct net_device *dev;
- read_lock(&dev_base_lock);
- dev = __dev_get_by_name(name);
- read_unlock(&dev_base_lock);
- return dev != NULL;
+ read_lock(&dev_base_lock);
+ dev = __dev_get_by_name(name);
+ read_unlock(&dev_base_lock);
+ return dev != NULL;
}
/**
struct net_device * __dev_get_by_index(int ifindex)
{
- struct net_device *dev;
+ struct net_device *dev;
- for (dev = dev_base; dev != NULL; dev = dev->next) {
- if (dev->ifindex == ifindex)
- return dev;
- }
- return NULL;
+ for (dev = dev_base; dev != NULL; dev = dev->next) {
+ if (dev->ifindex == ifindex)
+ return dev;
+ }
+ return NULL;
}
struct net_device * dev_get_by_index(int ifindex)
{
- struct net_device *dev;
-
- read_lock(&dev_base_lock);
- dev = __dev_get_by_index(ifindex);
- if (dev)
- dev_hold(dev);
- read_unlock(&dev_base_lock);
- return dev;
+ struct net_device *dev;
+
+ read_lock(&dev_base_lock);
+ dev = __dev_get_by_index(ifindex);
+ if (dev)
+ dev_hold(dev);
+ read_unlock(&dev_base_lock);
+ return dev;
}
/**
struct net_device *dev_getbyhwaddr(unsigned short type, char *ha)
{
- struct net_device *dev;
-
- for (dev = dev_base; dev != NULL; dev = dev->next) {
- if (dev->type == type &&
- memcmp(dev->dev_addr, ha, dev->addr_len) == 0)
- return dev;
- }
- return NULL;
+ struct net_device *dev;
+
+ for (dev = dev_base; dev != NULL; dev = dev->next) {
+ if (dev->type == type &&
+ memcmp(dev->dev_addr, ha, dev->addr_len) == 0)
+ return dev;
+ }
+ return NULL;
}
/**
int dev_alloc_name(struct net_device *dev, const char *name)
{
- int i;
- char buf[32];
- char *p;
-
- /*
- * Verify the string as this thing may have come from
- * the user. There must be either one "%d" and no other "%"
- * characters, or no "%" characters at all.
- */
- p = strchr(name, '%');
- if (p && (p[1] != 'd' || strchr(p+2, '%')))
- return -EINVAL;
-
- /*
- * If you need over 100 please also fix the algorithm...
- */
- for (i = 0; i < 100; i++) {
- snprintf(buf,sizeof(buf),name,i);
- if (__dev_get_by_name(buf) == NULL) {
- strcpy(dev->name, buf);
- return i;
- }
- }
- return -ENFILE; /* Over 100 of the things .. bail out! */
+ int i;
+ char buf[32];
+ char *p;
+
+ /*
+ * Verify the string as this thing may have come from
+ * the user. There must be either one "%d" and no other "%"
+ * characters, or no "%" characters at all.
+ */
+ p = strchr(name, '%');
+ if (p && (p[1] != 'd' || strchr(p+2, '%')))
+ return -EINVAL;
+
+ /*
+ * If you need over 100 please also fix the algorithm...
+ */
+ for (i = 0; i < 100; i++) {
+ snprintf(buf,sizeof(buf),name,i);
+ if (__dev_get_by_name(buf) == NULL) {
+ strcpy(dev->name, buf);
+ return i;
+ }
+ }
+ return -ENFILE; /* Over 100 of the things .. bail out! */
}
/**
struct net_device *dev_alloc(const char *name, int *err)
{
- struct net_device *dev=kmalloc(sizeof(struct net_device), GFP_KERNEL);
- if (dev == NULL) {
- *err = -ENOBUFS;
- return NULL;
- }
- memset(dev, 0, sizeof(struct net_device));
- *err = dev_alloc_name(dev, name);
- if (*err < 0) {
- kfree(dev);
- return NULL;
- }
- return dev;
+ struct net_device *dev=kmalloc(sizeof(struct net_device), GFP_KERNEL);
+ if (dev == NULL) {
+ *err = -ENOBUFS;
+ return NULL;
+ }
+ memset(dev, 0, sizeof(struct net_device));
+ *err = dev_alloc_name(dev, name);
+ if (*err < 0) {
+ kfree(dev);
+ return NULL;
+ }
+ return dev;
}
/**
void netdev_state_change(struct net_device *dev)
{
- if (dev->flags&IFF_UP) {
- notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);
- rtmsg_ifinfo(RTM_NEWLINK, dev, 0);
- }
+ if (dev->flags&IFF_UP) {
+ notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);
+ rtmsg_ifinfo(RTM_NEWLINK, dev, 0);
+ }
}
void dev_load(const char *name)
{
- if (!dev_get(name) && capable(CAP_SYS_MODULE))
- request_module(name);
+ if (!dev_get(name) && capable(CAP_SYS_MODULE))
+ request_module(name);
}
#else
static int default_rebuild_header(struct sk_buff *skb)
{
- printk(KERN_DEBUG "%s: default_rebuild_header called -- BUG!\n", skb->dev ? skb->dev->name : "NULL!!!");
- kfree_skb(skb);
- return 1;
+ printk(KERN_DEBUG "%s: default_rebuild_header called -- BUG!\n",
+ skb->dev ? skb->dev->name : "NULL!!!");
+ kfree_skb(skb);
+ return 1;
}
/**
int dev_open(struct net_device *dev)
{
- int ret = 0;
-
- /*
- * Is it already up?
- */
-
- if (dev->flags&IFF_UP)
- return 0;
-
- /*
- * Is it even present?
- */
- if (!netif_device_present(dev))
- return -ENODEV;
-
- /*
- * Call device private open method
- */
- if (try_inc_mod_count(dev->owner)) {
- if (dev->open) {
- ret = dev->open(dev);
- if (ret != 0 && dev->owner)
- __MOD_DEC_USE_COUNT(dev->owner);
- }
- } else {
- ret = -ENODEV;
- }
-
- /*
- * If it went open OK then:
- */
+ int ret = 0;
+
+ /*
+ * Is it already up?
+ */
+
+ if (dev->flags&IFF_UP)
+ return 0;
+
+ /*
+ * Is it even present?
+ */
+ if (!netif_device_present(dev))
+ return -ENODEV;
+
+ /*
+ * Call device private open method
+ */
+ if (try_inc_mod_count(dev->owner)) {
+ if (dev->open) {
+ ret = dev->open(dev);
+ if (ret != 0 && dev->owner)
+ __MOD_DEC_USE_COUNT(dev->owner);
+ }
+ } else {
+ ret = -ENODEV;
+ }
+
+ /*
+ * If it went open OK then:
+ */
- if (ret == 0)
- {
- /*
- * Set the flags.
- */
- dev->flags |= IFF_UP;
-
- set_bit(__LINK_STATE_START, &dev->state);
-
- /*
- * Initialize multicasting status
- */
- dev_mc_upload(dev);
-
- /*
- * Wakeup transmit queue engine
- */
- dev_activate(dev);
-
- /*
- * ... and announce new interface.
- */
- notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
- }
- return(ret);
+ if (ret == 0)
+ {
+ /*
+ * Set the flags.
+ */
+ dev->flags |= IFF_UP;
+
+ set_bit(__LINK_STATE_START, &dev->state);
+
+ /*
+ * Initialize multicasting status
+ */
+ dev_mc_upload(dev);
+
+ /*
+ * Wakeup transmit queue engine
+ */
+ dev_activate(dev);
+
+ /*
+ * ... and announce new interface.
+ */
+ notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
+ }
+ return(ret);
}
int dev_close(struct net_device *dev)
{
- if (!(dev->flags&IFF_UP))
- return 0;
-
- /*
- * Tell people we are going down, so that they can
- * prepare to death, when device is still operating.
- */
- notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev);
-
- dev_deactivate(dev);
-
- clear_bit(__LINK_STATE_START, &dev->state);
-
- /*
- * Call the device specific close. This cannot fail.
- * Only if device is UP
- *
- * We allow it to be called even after a DETACH hot-plug
- * event.
- */
+ if (!(dev->flags&IFF_UP))
+ return 0;
+
+ /*
+ * Tell people we are going down, so that they can
+ * prepare to death, when device is still operating.
+ */
+ notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev);
+
+ dev_deactivate(dev);
+
+ clear_bit(__LINK_STATE_START, &dev->state);
+
+ /*
+ * Call the device specific close. This cannot fail.
+ * Only if device is UP
+ *
+ * We allow it to be called even after a DETACH hot-plug
+ * event.
+ */
- if (dev->stop)
- dev->stop(dev);
+ if (dev->stop)
+ dev->stop(dev);
- /*
- * Device is now down.
- */
+ /*
+ * Device is now down.
+ */
- dev->flags &= ~IFF_UP;
+ dev->flags &= ~IFF_UP;
- /*
- * Tell people we are down
- */
- notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
+ /*
+ * Tell people we are down
+ */
+ notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
- /*
- * Drop the module refcount
- */
- if (dev->owner)
- __MOD_DEC_USE_COUNT(dev->owner);
+ /*
+ * Drop the module refcount
+ */
+ if (dev->owner)
+ __MOD_DEC_USE_COUNT(dev->owner);
- return(0);
+ return(0);
}
static inline int
illegal_highdma(struct net_device *dev, struct sk_buff *skb)
{
- int i;
+ int i;
- if (dev->features&NETIF_F_HIGHDMA)
- return 0;
+ if (dev->features&NETIF_F_HIGHDMA)
+ return 0;
- for (i=0; i<skb_shinfo(skb)->nr_frags; i++)
- if (skb_shinfo(skb)->frags[i].page >= highmem_start_page)
- return 1;
+ for (i=0; i<skb_shinfo(skb)->nr_frags; i++)
+ if (skb_shinfo(skb)->frags[i].page >= highmem_start_page)
+ return 1;
- return 0;
+ return 0;
}
#else
#define illegal_highdma(dev, skb) (0)
#endif
-/**
- * dev_queue_xmit - transmit a buffer
- * @skb: buffer to transmit
+/*
+ * dev_queue_xmit - transmit a buffer
+ * @skb: buffer to transmit
*
- * Queue a buffer for transmission to a network device. The caller must
- * have set the device and priority and built the buffer before calling this
- * function. The function can be called from an interrupt.
+ * Queue a buffer for transmission to a network device. The caller must
+ * have set the device and priority and built the buffer before calling this
+ * function. The function can be called from an interrupt.
*
- * A negative errno code is returned on a failure. A success does not
- * guarantee the frame will be transmitted as it may be dropped due
- * to congestion or traffic shaping.
+ * A negative errno code is returned on a failure. A success does not
+ * guarantee the frame will be transmitted as it may be dropped due
+ * to congestion or traffic shaping.
*/
int dev_queue_xmit(struct sk_buff *skb)
{
- struct net_device *dev = skb->dev;
- struct Qdisc *q;
+ struct net_device *dev = skb->dev;
- if (!(dev->features&NETIF_F_SG))
- {
- printk("NIC doesn't do scatter-gather!\n");
- BUG();
- }
+ if (!(dev->features&NETIF_F_SG))
+ {
+ printk("NIC doesn't do scatter-gather!\n");
+ BUG();
+ }
- if (skb_shinfo(skb)->frag_list &&
- !(dev->features&NETIF_F_FRAGLIST) &&
- skb_linearize(skb, GFP_ATOMIC) != 0) {
- kfree_skb(skb);
- return -ENOMEM;
- }
-
- /* Fragmented skb is linearized if device does not support SG,
- * or if at least one of fragments is in highmem and device
- * does not support DMA from it.
- */
- if (skb_shinfo(skb)->nr_frags &&
- (!(dev->features&NETIF_F_SG) || illegal_highdma(dev, skb)) &&
- skb_linearize(skb, GFP_ATOMIC) != 0) {
- kfree_skb(skb);
- return -ENOMEM;
- }
-
- /* Grab device queue */
- spin_lock_bh(&dev->queue_lock);
- q = dev->qdisc;
- if (q->enqueue) {
- int ret = q->enqueue(skb, q);
-
- qdisc_run(dev);
-
- spin_unlock_bh(&dev->queue_lock);
- return ret == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : ret;
- }
-
- /* The device has no queue. Common case for software devices:
- loopback, all the sorts of tunnels...
-
- Really, it is unlikely that xmit_lock protection is necessary here.
- (f.e. loopback and IP tunnels are clean ignoring statistics counters.)
- However, it is possible, that they rely on protection
- made by us here.
-
- Check this and shot the lock. It is not prone from deadlocks.
- Either shot noqueue qdisc, it is even simpler 8)
- */
- if (dev->flags&IFF_UP) {
- int cpu = smp_processor_id();
-
- if (dev->xmit_lock_owner != cpu) {
- spin_unlock(&dev->queue_lock);
- spin_lock(&dev->xmit_lock);
- dev->xmit_lock_owner = cpu;
-
- if (!netif_queue_stopped(dev)) {
- if (dev->hard_start_xmit(skb, dev) == 0) {
- dev->xmit_lock_owner = -1;
- spin_unlock_bh(&dev->xmit_lock);
- return 0;
- }
- }
- dev->xmit_lock_owner = -1;
- spin_unlock_bh(&dev->xmit_lock);
- kfree_skb(skb);
- return -ENETDOWN;
- } else {
- /* Recursion is detected! It is possible, unfortunately */
- }
- }
- spin_unlock_bh(&dev->queue_lock);
-
- kfree_skb(skb);
- return -ENETDOWN;
+ if (skb_shinfo(skb)->frag_list &&
+ !(dev->features&NETIF_F_FRAGLIST) &&
+ skb_linearize(skb, GFP_ATOMIC) != 0) {
+ kfree_skb(skb);
+ return -ENOMEM;
+ }
+
+ spin_lock_bh(&dev->queue_lock);
+ if (dev->flags&IFF_UP) {
+ int cpu = smp_processor_id();
+
+ if (dev->xmit_lock_owner != cpu) {
+ spin_unlock(&dev->queue_lock);
+ spin_lock(&dev->xmit_lock);
+ dev->xmit_lock_owner = cpu;
+
+ if (!netif_queue_stopped(dev)) {
+ if (dev->hard_start_xmit(skb, dev) == 0) {
+ dev->xmit_lock_owner = -1;
+ spin_unlock_bh(&dev->xmit_lock);
+ return 0;
+ }
+ }
+ dev->xmit_lock_owner = -1;
+ spin_unlock_bh(&dev->xmit_lock);
+ kfree_skb(skb);
+ return -ENETDOWN;
+ }
+ }
+ spin_unlock_bh(&dev->queue_lock);
+
+ kfree_skb(skb);
+ return -ENETDOWN;
}
static struct
{
- void (*stimul)(struct net_device *);
- struct net_device *dev;
+ void (*stimul)(struct net_device *);
+ struct net_device *dev;
} netdev_fc_slots[BITS_PER_LONG];
-int netdev_register_fc(struct net_device *dev, void (*stimul)(struct net_device *dev))
+int netdev_register_fc(struct net_device *dev,
+ void (*stimul)(struct net_device *dev))
{
- int bit = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&netdev_fc_lock, flags);
- if (netdev_fc_mask != ~0UL) {
- bit = ffz(netdev_fc_mask);
- netdev_fc_slots[bit].stimul = stimul;
- netdev_fc_slots[bit].dev = dev;
- set_bit(bit, &netdev_fc_mask);
- clear_bit(bit, &netdev_fc_xoff);
- }
- spin_unlock_irqrestore(&netdev_fc_lock, flags);
- return bit;
+ int bit = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&netdev_fc_lock, flags);
+ if (netdev_fc_mask != ~0UL) {
+ bit = ffz(netdev_fc_mask);
+ netdev_fc_slots[bit].stimul = stimul;
+ netdev_fc_slots[bit].dev = dev;
+ set_bit(bit, &netdev_fc_mask);
+ clear_bit(bit, &netdev_fc_xoff);
+ }
+ spin_unlock_irqrestore(&netdev_fc_lock, flags);
+ return bit;
}
void netdev_unregister_fc(int bit)
{
- unsigned long flags;
-
- spin_lock_irqsave(&netdev_fc_lock, flags);
- if (bit > 0) {
- netdev_fc_slots[bit].stimul = NULL;
- netdev_fc_slots[bit].dev = NULL;
- clear_bit(bit, &netdev_fc_mask);
- clear_bit(bit, &netdev_fc_xoff);
- }
- spin_unlock_irqrestore(&netdev_fc_lock, flags);
+ unsigned long flags;
+
+ spin_lock_irqsave(&netdev_fc_lock, flags);
+ if (bit > 0) {
+ netdev_fc_slots[bit].stimul = NULL;
+ netdev_fc_slots[bit].dev = NULL;
+ clear_bit(bit, &netdev_fc_mask);
+ clear_bit(bit, &netdev_fc_xoff);
+ }
+ spin_unlock_irqrestore(&netdev_fc_lock, flags);
}
static void netdev_wakeup(void)
{
- unsigned long xoff;
-
- spin_lock(&netdev_fc_lock);
- xoff = netdev_fc_xoff;
- netdev_fc_xoff = 0;
- while (xoff) {
- int i = ffz(~xoff);
- xoff &= ~(1<<i);
- netdev_fc_slots[i].stimul(netdev_fc_slots[i].dev);
- }
- spin_unlock(&netdev_fc_lock);
+ unsigned long xoff;
+
+ spin_lock(&netdev_fc_lock);
+ xoff = netdev_fc_xoff;
+ netdev_fc_xoff = 0;
+ while (xoff) {
+ int i = ffz(~xoff);
+ xoff &= ~(1<<i);
+ netdev_fc_slots[i].stimul(netdev_fc_slots[i].dev);
+ }
+ spin_unlock(&netdev_fc_lock);
}
#endif
-static void get_sample_stats(int cpu)
-{
- int blog = softnet_data[cpu].input_pkt_queue.qlen;
- int avg_blog = softnet_data[cpu].avg_blog;
-
- avg_blog = (avg_blog >> 1)+ (blog >> 1);
-
- if (avg_blog > mod_cong) {
- /* Above moderate congestion levels. */
- softnet_data[cpu].cng_level = NET_RX_CN_HIGH;
- } else if (avg_blog > lo_cong) {
- softnet_data[cpu].cng_level = NET_RX_CN_MOD;
- } else if (avg_blog > no_cong)
- softnet_data[cpu].cng_level = NET_RX_CN_LOW;
- else /* no congestion */
- softnet_data[cpu].cng_level = NET_RX_SUCCESS;
-
- softnet_data[cpu].avg_blog = avg_blog;
-}
-
void deliver_packet(struct sk_buff *skb, net_vif_t *vif)
{
- net_shadow_ring_t *shadow_ring;
- rx_shadow_entry_t *rx;
- unsigned long *g_pte;
- struct pfn_info *g_pfn, *h_pfn;
- unsigned int i;
-
- memset(skb->mac.ethernet->h_dest, 0, ETH_ALEN);
- if ( ntohs(skb->mac.ethernet->h_proto) == ETH_P_ARP )
- {
- memset(skb->nh.raw + 18, 0, ETH_ALEN);
- }
- shadow_ring = vif->shadow_ring;
+ net_shadow_ring_t *shadow_ring;
+ rx_shadow_entry_t *rx;
+ unsigned long *g_pte;
+ struct pfn_info *g_pfn, *h_pfn;
+ unsigned int i;
- if ( (i = shadow_ring->rx_cons) == shadow_ring->rx_prod )
- {
- return;
- }
+ memset(skb->mac.ethernet->h_dest, 0, ETH_ALEN);
+ if ( ntohs(skb->mac.ethernet->h_proto) == ETH_P_ARP )
+ {
+ memset(skb->nh.raw + 18, 0, ETH_ALEN);
+ }
+ shadow_ring = vif->shadow_ring;
- if ( shadow_ring->rx_ring[i].status != RING_STATUS_OK )
- {
- DPRINTK("Bad buffer in deliver_packet()\n");
- shadow_ring->rx_cons = RX_RING_INC(i);
- return;
- }
+ if ( (i = shadow_ring->rx_cons) == shadow_ring->rx_prod )
+ {
+ return;
+ }
+
+ if ( shadow_ring->rx_ring[i].status != RING_STATUS_OK )
+ {
+ DPRINTK("Bad buffer in deliver_packet()\n");
+ shadow_ring->rx_cons = RX_RING_INC(i);
+ return;
+ }
- rx = shadow_ring->rx_ring + i;
- if ( (skb->len + ETH_HLEN) < rx->size )
- rx->size = skb->len + ETH_HLEN;
+ rx = shadow_ring->rx_ring + i;
+ if ( (skb->len + ETH_HLEN) < rx->size )
+ rx->size = skb->len + ETH_HLEN;
- g_pte = map_domain_mem(rx->addr);
+ g_pte = map_domain_mem(rx->addr);
- g_pfn = frame_table + (*g_pte >> PAGE_SHIFT);
- h_pfn = skb->pf;
+ g_pfn = frame_table + (*g_pte >> PAGE_SHIFT);
+ h_pfn = skb->pf;
- h_pfn->tot_count = h_pfn->type_count = 1;
- g_pfn->tot_count = g_pfn->type_count = 0;
- h_pfn->flags = g_pfn->flags & (~PG_type_mask);
+ h_pfn->tot_count = h_pfn->type_count = 1;
+ g_pfn->tot_count = g_pfn->type_count = 0;
+ h_pfn->flags = g_pfn->flags & (~PG_type_mask);
- if (*g_pte & _PAGE_RW) h_pfn->flags |= PGT_writeable_page;
- g_pfn->flags = 0;
+ if (*g_pte & _PAGE_RW) h_pfn->flags |= PGT_writeable_page;
+ g_pfn->flags = 0;
- /* Point the guest at the new machine frame. */
- machine_to_phys_mapping[h_pfn - frame_table]
- = machine_to_phys_mapping[g_pfn - frame_table];
- *g_pte = (*g_pte & ~PAGE_MASK)
- | (((h_pfn - frame_table) << PAGE_SHIFT) & PAGE_MASK);
- *g_pte |= _PAGE_PRESENT;
+ /* Point the guest at the new machine frame. */
+ machine_to_phys_mapping[h_pfn - frame_table]
+ = machine_to_phys_mapping[g_pfn - frame_table];
+ *g_pte = (*g_pte & ~PAGE_MASK)
+ | (((h_pfn - frame_table) << PAGE_SHIFT) & PAGE_MASK);
+ *g_pte |= _PAGE_PRESENT;
- unmap_domain_mem(g_pte);
+ unmap_domain_mem(g_pte);
- /* Our skbuff now points at the guest's old frame. */
- skb->pf = g_pfn;
+ /* Our skbuff now points at the guest's old frame. */
+ skb->pf = g_pfn;
- shadow_ring->rx_cons = RX_RING_INC(i);
+ shadow_ring->rx_cons = RX_RING_INC(i);
}
/* Deliver skb to an old protocol, which is not threaded well
int netif_rx(struct sk_buff *skb)
{
#ifdef CONFIG_SMP
- unsigned long cpu_mask;
+ unsigned long cpu_mask;
#endif
- struct task_struct *p;
- int this_cpu = smp_processor_id();
- struct softnet_data *queue;
- unsigned long flags;
- net_vif_t *vif;
+ struct task_struct *p;
+ int this_cpu = smp_processor_id();
+ struct softnet_data *queue;
+ unsigned long flags;
+ net_vif_t *vif;
- local_irq_save(flags);
+ local_irq_save(flags);
- if (skb->skb_type != SKB_ZERO_COPY)
- BUG();
-
- if (skb->stamp.tv_sec == 0)
- get_fast_time(&skb->stamp);
-
- if ( (skb->data - skb->head) != (18 + ETH_HLEN) )
- BUG();
+ ASSERT(skb->skb_type == SKB_ZERO_COPY);
+ ASSERT((skb->data - skb->head) == (18 + ETH_HLEN));
- skb->head = (u8 *)map_domain_mem(((skb->pf - frame_table) << PAGE_SHIFT));
+ skb->head = (u8 *)map_domain_mem(((skb->pf - frame_table) << PAGE_SHIFT));
- /*
- * remapping this address really screws up all the skb pointers. We
- * need to map them all here sufficiently to get the packet
- * demultiplexed. this remapping happens more than once in the code and
- * is grim. It will be fixed in a later update -- drivers should be
- * able to align the packet arbitrarily.
- */
+ /*
+ * remapping this address really screws up all the skb pointers. We
+ * need to map them all here sufficiently to get the packet
+ * demultiplexed. this remapping happens more than once in the code and
+ * is grim. It will be fixed in a later update -- drivers should be
+ * able to align the packet arbitrarily.
+ */
- skb->data = skb->head;
- skb_reserve(skb,18); /* 18 is the 16 from dev_alloc_skb plus 2 for
- IP header alignment. */
- skb->mac.raw = skb->data;
- skb->data += ETH_HLEN;
- skb->nh.raw = skb->data;
+ skb->data = skb->head;
+ skb_reserve(skb,18); /* 18 is the 16 from dev_alloc_skb plus 2 for
+ IP header alignment. */
+ skb->mac.raw = skb->data;
+ skb->data += ETH_HLEN;
+ skb->nh.raw = skb->data;
- queue = &softnet_data[this_cpu];
+ queue = &softnet_data[this_cpu];
- netdev_rx_stat[this_cpu].total++;
+ netdev_rx_stat[this_cpu].total++;
- if ( skb->src_vif == VIF_UNKNOWN_INTERFACE )
- skb->src_vif = VIF_PHYSICAL_INTERFACE;
+ if ( skb->src_vif == VIF_UNKNOWN_INTERFACE )
+ skb->src_vif = VIF_PHYSICAL_INTERFACE;
- if ( skb->dst_vif == VIF_UNKNOWN_INTERFACE )
- skb->dst_vif = __net_get_target_vif(skb->mac.raw, skb->len, skb->src_vif);
+ if ( skb->dst_vif == VIF_UNKNOWN_INTERFACE )
+ skb->dst_vif = __net_get_target_vif(skb->mac.raw,
+ skb->len, skb->src_vif);
- if ( (vif = sys_vif_list[skb->dst_vif]) == NULL )
- goto drop;
+ if ( (vif = sys_vif_list[skb->dst_vif]) == NULL )
+ goto drop;
- /*
- * This lock-and-walk of the task list isn't really necessary, and is
- * an artifact of the old code. The vif contains a pointer to the skb
- * list we are going to queue the packet in, so the lock and the inner
- * loop could be removed. The argument against this is a possible race
- * in which a domain is killed as packets are being delivered to it.
- * This would result in the dest vif vanishing before we can deliver to
- * it.
- */
+ /*
+ * This lock-and-walk of the task list isn't really necessary, and is
+ * an artifact of the old code. The vif contains a pointer to the skb
+ * list we are going to queue the packet in, so the lock and the inner
+ * loop could be removed. The argument against this is a possible race
+ * in which a domain is killed as packets are being delivered to it.
+ * This would result in the dest vif vanishing before we can deliver to
+ * it.
+ */
- if ( skb->dst_vif >= VIF_PHYSICAL_INTERFACE )
- {
- read_lock(&tasklist_lock);
- p = &idle0_task;
- do {
- if ( p->domain != vif->domain ) continue;
- if ( vif->skb_list.qlen > 100 ) break;
- deliver_packet(skb, vif);
- cpu_mask = mark_hyp_event(p, _HYP_EVENT_NET_RX);
- read_unlock(&tasklist_lock);
- goto found;
- }
- while ( (p = p->next_task) != &idle0_task );
- read_unlock(&tasklist_lock);
- goto drop;
+ if ( skb->dst_vif >= VIF_PHYSICAL_INTERFACE )
+ {
+ read_lock(&tasklist_lock);
+ p = &idle0_task;
+ do {
+ if ( p->domain != vif->domain ) continue;
+ if ( vif->skb_list.qlen > 100 ) break;
+ deliver_packet(skb, vif);
+ cpu_mask = mark_hyp_event(p, _HYP_EVENT_NET_RX);
+ read_unlock(&tasklist_lock);
+ goto found;
}
+ while ( (p = p->next_task) != &idle0_task );
+ read_unlock(&tasklist_lock);
+ goto drop;
+ }
-drop:
- netdev_rx_stat[this_cpu].dropped++;
- unmap_domain_mem(skb->head);
- kfree_skb(skb);
- local_irq_restore(flags);
- return NET_RX_DROP;
-
-found:
- unmap_domain_mem(skb->head);
- skb->head = skb->data = skb->tail = (void *)0xdeadbeef;
- kfree_skb(skb);
- hyp_event_notify(cpu_mask);
- local_irq_restore(flags);
- return 0;
+ drop:
+ netdev_rx_stat[this_cpu].dropped++;
+ unmap_domain_mem(skb->head);
+ kfree_skb(skb);
+ local_irq_restore(flags);
+ return NET_RX_DROP;
+
+ found:
+ unmap_domain_mem(skb->head);
+ skb->head = skb->data = skb->tail = (void *)0xdeadbeef;
+ kfree_skb(skb);
+ hyp_event_notify(cpu_mask);
+ local_irq_restore(flags);
+ return 0;
}
-static int deliver_to_old_ones(struct packet_type *pt, struct sk_buff *skb, int last)
+static int deliver_to_old_ones(struct packet_type *pt,
+ struct sk_buff *skb, int last)
{
- static spinlock_t net_bh_lock = SPIN_LOCK_UNLOCKED;
- int ret = NET_RX_DROP;
+ static spinlock_t net_bh_lock = SPIN_LOCK_UNLOCKED;
+ int ret = NET_RX_DROP;
- if (!last) {
- skb = skb_clone(skb, GFP_ATOMIC);
- if (skb == NULL)
- return ret;
- }
- if (skb_is_nonlinear(skb) && skb_linearize(skb, GFP_ATOMIC) != 0) {
- kfree_skb(skb);
- return ret;
- }
+ if (!last) {
+ skb = skb_clone(skb, GFP_ATOMIC);
+ if (skb == NULL)
+ return ret;
+ }
+ if (skb_is_nonlinear(skb) && skb_linearize(skb, GFP_ATOMIC) != 0) {
+ kfree_skb(skb);
+ return ret;
+ }
- /* The assumption (correct one) is that old protocols
- did not depened on BHs different of NET_BH and TIMER_BH.
- */
+ /* The assumption (correct one) is that old protocols
+ did not depened on BHs different of NET_BH and TIMER_BH.
+ */
- /* Emulate NET_BH with special spinlock */
- spin_lock(&net_bh_lock);
+ /* Emulate NET_BH with special spinlock */
+ spin_lock(&net_bh_lock);
- /* Disable timers and wait for all timers completion */
- tasklet_disable(bh_task_vec+TIMER_BH);
+ /* Disable timers and wait for all timers completion */
+ tasklet_disable(bh_task_vec+TIMER_BH);
- ret = pt->func(skb, skb->dev, pt);
+ ret = pt->func(skb, skb->dev, pt);
- tasklet_hi_enable(bh_task_vec+TIMER_BH);
- spin_unlock(&net_bh_lock);
- return ret;
+ tasklet_hi_enable(bh_task_vec+TIMER_BH);
+ spin_unlock(&net_bh_lock);
+ return ret;
}
-static void net_tx_action(struct softirq_action *h)
+static void net_tx_action(unsigned long unused)
{
- int cpu = smp_processor_id();
-
- if (softnet_data[cpu].completion_queue) {
- struct sk_buff *clist;
-
- local_irq_disable();
- clist = softnet_data[cpu].completion_queue;
- softnet_data[cpu].completion_queue = NULL;
- local_irq_enable();
-
- while (clist != NULL) {
- struct sk_buff *skb = clist;
- clist = clist->next;
-
- BUG_TRAP(atomic_read(&skb->users) == 0);
- __kfree_skb(skb);
- }
- }
-
- if (softnet_data[cpu].output_queue) {
- struct net_device *head;
-
- local_irq_disable();
- head = softnet_data[cpu].output_queue;
- softnet_data[cpu].output_queue = NULL;
- local_irq_enable();
-
- while (head != NULL) {
- struct net_device *dev = head;
- head = head->next_sched;
-
- smp_mb__before_clear_bit();
- clear_bit(__LINK_STATE_SCHED, &dev->state);
-
- if (spin_trylock(&dev->queue_lock)) {
- qdisc_run(dev);
- spin_unlock(&dev->queue_lock);
- } else {
- netif_schedule(dev);
- }
- }
- }
-}
+ int cpu = smp_processor_id();
+
+ if (softnet_data[cpu].completion_queue) {
+ struct sk_buff *clist;
+
+ local_irq_disable();
+ clist = softnet_data[cpu].completion_queue;
+ softnet_data[cpu].completion_queue = NULL;
+ local_irq_enable();
+
+ while (clist != NULL) {
+ struct sk_buff *skb = clist;
+ clist = clist->next;
+
+ BUG_TRAP(atomic_read(&skb->users) == 0);
+ __kfree_skb(skb);
+ }
+ }
+
+ if (softnet_data[cpu].output_queue) {
+ struct net_device *head;
+ local_irq_disable();
+ head = softnet_data[cpu].output_queue;
+ softnet_data[cpu].output_queue = NULL;
+ local_irq_enable();
+
+ while (head != NULL) {
+ struct net_device *dev = head;
+ head = head->next_sched;
+
+ smp_mb__before_clear_bit();
+ clear_bit(__LINK_STATE_SCHED, &dev->state);
+
+ if (spin_trylock(&dev->queue_lock)) {
+ /*qdisc_run(dev); XXX KAF */
+ spin_unlock(&dev->queue_lock);
+ } else {
+ netif_schedule(dev);
+ }
+ }
+ }
+}
+DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0);
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
void (*br_handle_frame_hook)(struct sk_buff *skb) = NULL;
#endif
static __inline__ int handle_bridge(struct sk_buff *skb,
- struct packet_type *pt_prev)
+ struct packet_type *pt_prev)
{
- int ret = NET_RX_DROP;
-
- if (pt_prev) {
- if (!pt_prev->data)
- ret = deliver_to_old_ones(pt_prev, skb, 0);
- else {
- atomic_inc(&skb->users);
- ret = pt_prev->func(skb, skb->dev, pt_prev);
- }
- }
+ int ret = NET_RX_DROP;
+
+ if (pt_prev) {
+ if (!pt_prev->data)
+ ret = deliver_to_old_ones(pt_prev, skb, 0);
+ else {
+ atomic_inc(&skb->users);
+ ret = pt_prev->func(skb, skb->dev, pt_prev);
+ }
+ }
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
- br_handle_frame_hook(skb);
+ br_handle_frame_hook(skb);
#endif
- return ret;
+ return ret;
}
#ifdef CONFIG_NET_DIVERT
static inline void handle_diverter(struct sk_buff *skb)
{
- /* if diversion is supported on device, then divert */
- if (skb->dev->divert && skb->dev->divert->divert)
- divert_frame(skb);
+ /* if diversion is supported on device, then divert */
+ if (skb->dev->divert && skb->dev->divert->divert)
+ divert_frame(skb);
}
#endif /* CONFIG_NET_DIVERT */
static int dev_ifname(struct ifreq *arg)
{
- struct net_device *dev;
- struct ifreq ifr;
+ struct net_device *dev;
+ struct ifreq ifr;
- /*
- * Fetch the caller's info block.
- */
+ /*
+ * Fetch the caller's info block.
+ */
- if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
- return -EFAULT;
-
- read_lock(&dev_base_lock);
- dev = __dev_get_by_index(ifr.ifr_ifindex);
- if (!dev) {
- read_unlock(&dev_base_lock);
- return -ENODEV;
- }
-
- strcpy(ifr.ifr_name, dev->name);
- read_unlock(&dev_base_lock);
-
- if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
- return -EFAULT;
- return 0;
+ if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
+ return -EFAULT;
+
+ read_lock(&dev_base_lock);
+ dev = __dev_get_by_index(ifr.ifr_ifindex);
+ if (!dev) {
+ read_unlock(&dev_base_lock);
+ return -ENODEV;
+ }
+
+ strcpy(ifr.ifr_name, dev->name);
+ read_unlock(&dev_base_lock);
+
+ if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
+ return -EFAULT;
+ return 0;
}
int netdev_set_master(struct net_device *slave, struct net_device *master)
{
- struct net_device *old = slave->master;
+ struct net_device *old = slave->master;
- if (master) {
- if (old)
- return -EBUSY;
- dev_hold(master);
- }
+ if (master) {
+ if (old)
+ return -EBUSY;
+ dev_hold(master);
+ }
- br_write_lock_bh(BR_NETPROTO_LOCK);
- slave->master = master;
- br_write_unlock_bh(BR_NETPROTO_LOCK);
+ br_write_lock_bh(BR_NETPROTO_LOCK);
+ slave->master = master;
+ br_write_unlock_bh(BR_NETPROTO_LOCK);
- if (old)
- dev_put(old);
+ if (old)
+ dev_put(old);
- if (master)
- slave->flags |= IFF_SLAVE;
- else
- slave->flags &= ~IFF_SLAVE;
+ if (master)
+ slave->flags |= IFF_SLAVE;
+ else
+ slave->flags &= ~IFF_SLAVE;
- rtmsg_ifinfo(RTM_NEWLINK, slave, IFF_SLAVE);
- return 0;
+ rtmsg_ifinfo(RTM_NEWLINK, slave, IFF_SLAVE);
+ return 0;
}
/**
void dev_set_promiscuity(struct net_device *dev, int inc)
{
- unsigned short old_flags = dev->flags;
+ unsigned short old_flags = dev->flags;
- dev->flags |= IFF_PROMISC;
- if ((dev->promiscuity += inc) == 0)
- dev->flags &= ~IFF_PROMISC;
- if (dev->flags^old_flags) {
+ dev->flags |= IFF_PROMISC;
+ if ((dev->promiscuity += inc) == 0)
+ dev->flags &= ~IFF_PROMISC;
+ if (dev->flags^old_flags) {
#ifdef CONFIG_NET_FASTROUTE
- if (dev->flags&IFF_PROMISC) {
- netdev_fastroute_obstacles++;
- dev_clear_fastroute(dev);
- } else
- netdev_fastroute_obstacles--;
+ if (dev->flags&IFF_PROMISC) {
+ netdev_fastroute_obstacles++;
+ dev_clear_fastroute(dev);
+ } else
+ netdev_fastroute_obstacles--;
#endif
- dev_mc_upload(dev);
- printk(KERN_INFO "device %s %s promiscuous mode\n",
- dev->name, (dev->flags&IFF_PROMISC) ? "entered" : "left");
- }
+ dev_mc_upload(dev);
+ printk(KERN_INFO "device %s %s promiscuous mode\n",
+ dev->name, (dev->flags&IFF_PROMISC) ? "entered" : "left");
+ }
}
/**
void dev_set_allmulti(struct net_device *dev, int inc)
{
- unsigned short old_flags = dev->flags;
+ unsigned short old_flags = dev->flags;
- dev->flags |= IFF_ALLMULTI;
- if ((dev->allmulti += inc) == 0)
- dev->flags &= ~IFF_ALLMULTI;
- if (dev->flags^old_flags)
- dev_mc_upload(dev);
+ dev->flags |= IFF_ALLMULTI;
+ if ((dev->allmulti += inc) == 0)
+ dev->flags &= ~IFF_ALLMULTI;
+ if (dev->flags^old_flags)
+ dev_mc_upload(dev);
}
int dev_change_flags(struct net_device *dev, unsigned flags)
{
- int ret;
- int old_flags = dev->flags;
-
- /*
- * Set the flags on our device.
- */
-
- dev->flags = (flags & (IFF_DEBUG|IFF_NOTRAILERS|IFF_NOARP|IFF_DYNAMIC|
- IFF_MULTICAST|IFF_PORTSEL|IFF_AUTOMEDIA)) |
- (dev->flags & (IFF_UP|IFF_VOLATILE|IFF_PROMISC|IFF_ALLMULTI));
-
- /*
- * Load in the correct multicast list now the flags have changed.
- */
-
- dev_mc_upload(dev);
-
- /*
- * Have we downed the interface. We handle IFF_UP ourselves
- * according to user attempts to set it, rather than blindly
- * setting it.
- */
-
- ret = 0;
- if ((old_flags^flags)&IFF_UP) /* Bit is different ? */
- {
- ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev);
-
- if (ret == 0)
- dev_mc_upload(dev);
- }
-
- if (dev->flags&IFF_UP &&
- ((old_flags^dev->flags)&~(IFF_UP|IFF_PROMISC|IFF_ALLMULTI|IFF_VOLATILE)))
- notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);
-
- if ((flags^dev->gflags)&IFF_PROMISC) {
- int inc = (flags&IFF_PROMISC) ? +1 : -1;
- dev->gflags ^= IFF_PROMISC;
- dev_set_promiscuity(dev, inc);
- }
-
- /* NOTE: order of synchronization of IFF_PROMISC and IFF_ALLMULTI
- is important. Some (broken) drivers set IFF_PROMISC, when
- IFF_ALLMULTI is requested not asking us and not reporting.
- */
- if ((flags^dev->gflags)&IFF_ALLMULTI) {
- int inc = (flags&IFF_ALLMULTI) ? +1 : -1;
- dev->gflags ^= IFF_ALLMULTI;
- dev_set_allmulti(dev, inc);
- }
-
- if (old_flags^dev->flags)
- rtmsg_ifinfo(RTM_NEWLINK, dev, old_flags^dev->flags);
-
- return ret;
+ int ret;
+ int old_flags = dev->flags;
+
+ /*
+ * Set the flags on our device.
+ */
+
+ dev->flags = (flags & (IFF_DEBUG|IFF_NOTRAILERS|IFF_NOARP|IFF_DYNAMIC|
+ IFF_MULTICAST|IFF_PORTSEL|IFF_AUTOMEDIA)) |
+ (dev->flags & (IFF_UP|IFF_VOLATILE|IFF_PROMISC|IFF_ALLMULTI));
+
+ /*
+ * Load in the correct multicast list now the flags have changed.
+ */
+
+ dev_mc_upload(dev);
+
+ /*
+ * Have we downed the interface. We handle IFF_UP ourselves
+ * according to user attempts to set it, rather than blindly
+ * setting it.
+ */
+
+ ret = 0;
+ if ((old_flags^flags)&IFF_UP) /* Bit is different ? */
+ {
+ ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev);
+
+ if (ret == 0)
+ dev_mc_upload(dev);
+ }
+
+ if (dev->flags&IFF_UP &&
+ ((old_flags^dev->flags)&
+ ~(IFF_UP|IFF_PROMISC|IFF_ALLMULTI|IFF_VOLATILE)))
+ notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);
+
+ if ((flags^dev->gflags)&IFF_PROMISC) {
+ int inc = (flags&IFF_PROMISC) ? +1 : -1;
+ dev->gflags ^= IFF_PROMISC;
+ dev_set_promiscuity(dev, inc);
+ }
+
+ /* NOTE: order of synchronization of IFF_PROMISC and IFF_ALLMULTI
+ is important. Some (broken) drivers set IFF_PROMISC, when
+ IFF_ALLMULTI is requested not asking us and not reporting.
+ */
+ if ((flags^dev->gflags)&IFF_ALLMULTI) {
+ int inc = (flags&IFF_ALLMULTI) ? +1 : -1;
+ dev->gflags ^= IFF_ALLMULTI;
+ dev_set_allmulti(dev, inc);
+ }
+
+ if (old_flags^dev->flags)
+ rtmsg_ifinfo(RTM_NEWLINK, dev, old_flags^dev->flags);
+
+ return ret;
}
/*
static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
{
- struct net_device *dev;
- int err;
-
- if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL)
- return -ENODEV;
-
- switch(cmd)
- {
- case SIOCGIFFLAGS: /* Get interface flags */
- ifr->ifr_flags = (dev->flags&~(IFF_PROMISC|IFF_ALLMULTI|IFF_RUNNING))
- |(dev->gflags&(IFF_PROMISC|IFF_ALLMULTI));
- if (netif_running(dev) && netif_carrier_ok(dev))
- ifr->ifr_flags |= IFF_RUNNING;
- return 0;
-
- case SIOCSIFFLAGS: /* Set interface flags */
- return dev_change_flags(dev, ifr->ifr_flags);
+ struct net_device *dev;
+ int err;
+
+ if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL)
+ return -ENODEV;
+
+ switch(cmd)
+ {
+ case SIOCGIFFLAGS: /* Get interface flags */
+ ifr->ifr_flags = (dev->flags&~(IFF_PROMISC|IFF_ALLMULTI|IFF_RUNNING))
+ |(dev->gflags&(IFF_PROMISC|IFF_ALLMULTI));
+ if (netif_running(dev) && netif_carrier_ok(dev))
+ ifr->ifr_flags |= IFF_RUNNING;
+ return 0;
+
+ case SIOCSIFFLAGS: /* Set interface flags */
+ return dev_change_flags(dev, ifr->ifr_flags);
- case SIOCGIFMETRIC: /* Get the metric on the interface (currently unused) */
- ifr->ifr_metric = 0;
- return 0;
+ case SIOCGIFMETRIC: /* Get the metric on the interface */
+ ifr->ifr_metric = 0;
+ return 0;
- case SIOCSIFMETRIC: /* Set the metric on the interface (currently unused) */
- return -EOPNOTSUPP;
+ case SIOCSIFMETRIC: /* Set the metric on the interface */
+ return -EOPNOTSUPP;
- case SIOCGIFMTU: /* Get the MTU of a device */
- ifr->ifr_mtu = dev->mtu;
- return 0;
+ case SIOCGIFMTU: /* Get the MTU of a device */
+ ifr->ifr_mtu = dev->mtu;
+ return 0;
- case SIOCSIFMTU: /* Set the MTU of a device */
- if (ifr->ifr_mtu == dev->mtu)
- return 0;
+ case SIOCSIFMTU: /* Set the MTU of a device */
+ if (ifr->ifr_mtu == dev->mtu)
+ return 0;
- /*
- * MTU must be positive.
- */
+ /*
+ * MTU must be positive.
+ */
- if (ifr->ifr_mtu<0)
- return -EINVAL;
-
- if (!netif_device_present(dev))
- return -ENODEV;
-
- if (dev->change_mtu)
- err = dev->change_mtu(dev, ifr->ifr_mtu);
- else {
- dev->mtu = ifr->ifr_mtu;
- err = 0;
- }
- if (!err && dev->flags&IFF_UP)
- notifier_call_chain(&netdev_chain, NETDEV_CHANGEMTU, dev);
- return err;
-
- case SIOCGIFHWADDR:
- memcpy(ifr->ifr_hwaddr.sa_data,dev->dev_addr, MAX_ADDR_LEN);
- ifr->ifr_hwaddr.sa_family=dev->type;
- return 0;
+ if (ifr->ifr_mtu<0)
+ return -EINVAL;
+
+ if (!netif_device_present(dev))
+ return -ENODEV;
+
+ if (dev->change_mtu)
+ err = dev->change_mtu(dev, ifr->ifr_mtu);
+ else {
+ dev->mtu = ifr->ifr_mtu;
+ err = 0;
+ }
+ if (!err && dev->flags&IFF_UP)
+ notifier_call_chain(&netdev_chain, NETDEV_CHANGEMTU, dev);
+ return err;
+
+ case SIOCGIFHWADDR:
+ memcpy(ifr->ifr_hwaddr.sa_data,dev->dev_addr, MAX_ADDR_LEN);
+ ifr->ifr_hwaddr.sa_family=dev->type;
+ return 0;
- case SIOCSIFHWADDR:
- if (dev->set_mac_address == NULL)
- return -EOPNOTSUPP;
- if (ifr->ifr_hwaddr.sa_family!=dev->type)
- return -EINVAL;
- if (!netif_device_present(dev))
- return -ENODEV;
- err = dev->set_mac_address(dev, &ifr->ifr_hwaddr);
- if (!err)
- notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);
- return err;
+ case SIOCSIFHWADDR:
+ if (dev->set_mac_address == NULL)
+ return -EOPNOTSUPP;
+ if (ifr->ifr_hwaddr.sa_family!=dev->type)
+ return -EINVAL;
+ if (!netif_device_present(dev))
+ return -ENODEV;
+ err = dev->set_mac_address(dev, &ifr->ifr_hwaddr);
+ if (!err)
+ notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);
+ return err;
- case SIOCSIFHWBROADCAST:
- if (ifr->ifr_hwaddr.sa_family!=dev->type)
- return -EINVAL;
- memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data, MAX_ADDR_LEN);
- notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);
- return 0;
-
- case SIOCGIFMAP:
- ifr->ifr_map.mem_start=dev->mem_start;
- ifr->ifr_map.mem_end=dev->mem_end;
- ifr->ifr_map.base_addr=dev->base_addr;
- ifr->ifr_map.irq=dev->irq;
- ifr->ifr_map.dma=dev->dma;
- ifr->ifr_map.port=dev->if_port;
- return 0;
+ case SIOCSIFHWBROADCAST:
+ if (ifr->ifr_hwaddr.sa_family!=dev->type)
+ return -EINVAL;
+ memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data, MAX_ADDR_LEN);
+ notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);
+ return 0;
+
+ case SIOCGIFMAP:
+ ifr->ifr_map.mem_start=dev->mem_start;
+ ifr->ifr_map.mem_end=dev->mem_end;
+ ifr->ifr_map.base_addr=dev->base_addr;
+ ifr->ifr_map.irq=dev->irq;
+ ifr->ifr_map.dma=dev->dma;
+ ifr->ifr_map.port=dev->if_port;
+ return 0;
- case SIOCSIFMAP:
- if (dev->set_config) {
- if (!netif_device_present(dev))
- return -ENODEV;
- return dev->set_config(dev,&ifr->ifr_map);
- }
- return -EOPNOTSUPP;
+ case SIOCSIFMAP:
+ if (dev->set_config) {
+ if (!netif_device_present(dev))
+ return -ENODEV;
+ return dev->set_config(dev,&ifr->ifr_map);
+ }
+ return -EOPNOTSUPP;
- case SIOCADDMULTI:
- if (dev->set_multicast_list == NULL ||
- ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
- return -EINVAL;
- if (!netif_device_present(dev))
- return -ENODEV;
- dev_mc_add(dev,ifr->ifr_hwaddr.sa_data, dev->addr_len, 1);
- return 0;
-
- case SIOCDELMULTI:
- if (dev->set_multicast_list == NULL ||
- ifr->ifr_hwaddr.sa_family!=AF_UNSPEC)
- return -EINVAL;
- if (!netif_device_present(dev))
- return -ENODEV;
- dev_mc_delete(dev,ifr->ifr_hwaddr.sa_data,dev->addr_len, 1);
- return 0;
-
- case SIOCGIFINDEX:
- ifr->ifr_ifindex = dev->ifindex;
- return 0;
-
- case SIOCGIFTXQLEN:
- ifr->ifr_qlen = dev->tx_queue_len;
- return 0;
-
- case SIOCSIFTXQLEN:
- if (ifr->ifr_qlen<0)
- return -EINVAL;
- dev->tx_queue_len = ifr->ifr_qlen;
- return 0;
-
- case SIOCSIFNAME:
- if (dev->flags&IFF_UP)
- return -EBUSY;
- if (__dev_get_by_name(ifr->ifr_newname))
- return -EEXIST;
- memcpy(dev->name, ifr->ifr_newname, IFNAMSIZ);
- dev->name[IFNAMSIZ-1] = 0;
- notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
- return 0;
+ case SIOCADDMULTI:
+ if (dev->set_multicast_list == NULL ||
+ ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
+ return -EINVAL;
+ if (!netif_device_present(dev))
+ return -ENODEV;
+ dev_mc_add(dev,ifr->ifr_hwaddr.sa_data, dev->addr_len, 1);
+ return 0;
+
+ case SIOCDELMULTI:
+ if (dev->set_multicast_list == NULL ||
+ ifr->ifr_hwaddr.sa_family!=AF_UNSPEC)
+ return -EINVAL;
+ if (!netif_device_present(dev))
+ return -ENODEV;
+ dev_mc_delete(dev,ifr->ifr_hwaddr.sa_data,dev->addr_len, 1);
+ return 0;
+
+ case SIOCGIFINDEX:
+ ifr->ifr_ifindex = dev->ifindex;
+ return 0;
+
+ case SIOCSIFNAME:
+ if (dev->flags&IFF_UP)
+ return -EBUSY;
+ if (__dev_get_by_name(ifr->ifr_newname))
+ return -EEXIST;
+ memcpy(dev->name, ifr->ifr_newname, IFNAMSIZ);
+ dev->name[IFNAMSIZ-1] = 0;
+ notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
+ return 0;
#ifdef WIRELESS_EXT
- case SIOCGIWSTATS:
- return dev_iwstats(dev, ifr);
+ case SIOCGIWSTATS:
+ return dev_iwstats(dev, ifr);
#endif /* WIRELESS_EXT */
- /*
- * Unknown or private ioctl
- */
-
- default:
- if ((cmd >= SIOCDEVPRIVATE &&
- cmd <= SIOCDEVPRIVATE + 15) ||
- cmd == SIOCBONDENSLAVE ||
- cmd == SIOCBONDRELEASE ||
- cmd == SIOCBONDSETHWADDR ||
- cmd == SIOCBONDSLAVEINFOQUERY ||
- cmd == SIOCBONDINFOQUERY ||
- cmd == SIOCBONDCHANGEACTIVE ||
- cmd == SIOCETHTOOL ||
- cmd == SIOCGMIIPHY ||
- cmd == SIOCGMIIREG ||
- cmd == SIOCSMIIREG) {
- if (dev->do_ioctl) {
- if (!netif_device_present(dev))
- return -ENODEV;
- return dev->do_ioctl(dev, ifr, cmd);
- }
- return -EOPNOTSUPP;
- }
+ /*
+ * Unknown or private ioctl
+ */
+
+ default:
+ if ((cmd >= SIOCDEVPRIVATE &&
+ cmd <= SIOCDEVPRIVATE + 15) ||
+ cmd == SIOCBONDENSLAVE ||
+ cmd == SIOCBONDRELEASE ||
+ cmd == SIOCBONDSETHWADDR ||
+ cmd == SIOCBONDSLAVEINFOQUERY ||
+ cmd == SIOCBONDINFOQUERY ||
+ cmd == SIOCBONDCHANGEACTIVE ||
+ cmd == SIOCETHTOOL ||
+ cmd == SIOCGMIIPHY ||
+ cmd == SIOCGMIIREG ||
+ cmd == SIOCSMIIREG) {
+ if (dev->do_ioctl) {
+ if (!netif_device_present(dev))
+ return -ENODEV;
+ return dev->do_ioctl(dev, ifr, cmd);
+ }
+ return -EOPNOTSUPP;
+ }
#ifdef WIRELESS_EXT
- if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
- if (dev->do_ioctl) {
- if (!netif_device_present(dev))
- return -ENODEV;
- return dev->do_ioctl(dev, ifr, cmd);
- }
- return -EOPNOTSUPP;
- }
+ if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
+ if (dev->do_ioctl) {
+ if (!netif_device_present(dev))
+ return -ENODEV;
+ return dev->do_ioctl(dev, ifr, cmd);
+ }
+ return -EOPNOTSUPP;
+ }
#endif /* WIRELESS_EXT */
- }
- return -EINVAL;
+ }
+ return -EINVAL;
}
/*
- * This function handles all "interface"-type I/O control requests. The actual
- * 'doing' part of this is dev_ifsioc above.
+ * This function handles all "interface"-type I/O control requests. The actual
+ * 'doing' part of this is dev_ifsioc above.
*/
/**
int dev_ioctl(unsigned int cmd, void *arg)
{
- struct ifreq ifr;
- int ret;
- char *colon;
-
- /* One special case: SIOCGIFCONF takes ifconf argument
- and requires shared lock, because it sleeps writing
- to user space.
- */
+ struct ifreq ifr;
+ int ret;
+ char *colon;
+
+ /* One special case: SIOCGIFCONF takes ifconf argument
+ and requires shared lock, because it sleeps writing
+ to user space.
+ */
- if (cmd == SIOCGIFCONF) {
- return -ENOSYS;
- }
- if (cmd == SIOCGIFNAME) {
- return dev_ifname((struct ifreq *)arg);
- }
+ if (cmd == SIOCGIFCONF) {
+ return -ENOSYS;
+ }
+ if (cmd == SIOCGIFNAME) {
+ return dev_ifname((struct ifreq *)arg);
+ }
- if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
- return -EFAULT;
+ if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
+ return -EFAULT;
- ifr.ifr_name[IFNAMSIZ-1] = 0;
+ ifr.ifr_name[IFNAMSIZ-1] = 0;
- colon = strchr(ifr.ifr_name, ':');
- if (colon)
- *colon = 0;
+ colon = strchr(ifr.ifr_name, ':');
+ if (colon)
+ *colon = 0;
- /*
- * See which interface the caller is talking about.
- */
+ /*
+ * See which interface the caller is talking about.
+ */
- switch(cmd)
- {
- /*
- * These ioctl calls:
- * - can be done by all.
- * - atomic and do not require locking.
- * - return a value
- */
+ switch(cmd)
+ {
+ /*
+ * These ioctl calls:
+ * - can be done by all.
+ * - atomic and do not require locking.
+ * - return a value
+ */
- case SIOCGIFFLAGS:
- case SIOCGIFMETRIC:
- case SIOCGIFMTU:
- case SIOCGIFHWADDR:
- case SIOCGIFSLAVE:
- case SIOCGIFMAP:
- case SIOCGIFINDEX:
- case SIOCGIFTXQLEN:
- dev_load(ifr.ifr_name);
- read_lock(&dev_base_lock);
- ret = dev_ifsioc(&ifr, cmd);
- read_unlock(&dev_base_lock);
- if (!ret) {
- if (colon)
- *colon = ':';
- if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
- return -EFAULT;
- }
- return ret;
-
- /*
- * These ioctl calls:
- * - require superuser power.
- * - require strict serialization.
- * - return a value
- */
+ case SIOCGIFFLAGS:
+ case SIOCGIFMETRIC:
+ case SIOCGIFMTU:
+ case SIOCGIFHWADDR:
+ case SIOCGIFSLAVE:
+ case SIOCGIFMAP:
+ case SIOCGIFINDEX:
+ dev_load(ifr.ifr_name);
+ read_lock(&dev_base_lock);
+ ret = dev_ifsioc(&ifr, cmd);
+ read_unlock(&dev_base_lock);
+ if (!ret) {
+ if (colon)
+ *colon = ':';
+ if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
+ return -EFAULT;
+ }
+ return ret;
+
+ /*
+ * These ioctl calls:
+ * - require superuser power.
+ * - require strict serialization.
+ * - return a value
+ */
- case SIOCETHTOOL:
- case SIOCGMIIPHY:
- case SIOCGMIIREG:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- dev_load(ifr.ifr_name);
- dev_probe_lock();
- rtnl_lock();
- ret = dev_ifsioc(&ifr, cmd);
- rtnl_unlock();
- dev_probe_unlock();
- if (!ret) {
- if (colon)
- *colon = ':';
- if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
- return -EFAULT;
- }
- return ret;
-
- /*
- * These ioctl calls:
- * - require superuser power.
- * - require strict serialization.
- * - do not return a value
- */
+ case SIOCETHTOOL:
+ case SIOCGMIIPHY:
+ case SIOCGMIIREG:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ dev_load(ifr.ifr_name);
+ dev_probe_lock();
+ rtnl_lock();
+ ret = dev_ifsioc(&ifr, cmd);
+ rtnl_unlock();
+ dev_probe_unlock();
+ if (!ret) {
+ if (colon)
+ *colon = ':';
+ if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
+ return -EFAULT;
+ }
+ return ret;
+
+ /*
+ * These ioctl calls:
+ * - require superuser power.
+ * - require strict serialization.
+ * - do not return a value
+ */
- case SIOCSIFFLAGS:
- case SIOCSIFMETRIC:
- case SIOCSIFMTU:
- case SIOCSIFMAP:
- case SIOCSIFHWADDR:
- case SIOCSIFSLAVE:
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- case SIOCSIFHWBROADCAST:
- case SIOCSIFTXQLEN:
- case SIOCSIFNAME:
- case SIOCSMIIREG:
- case SIOCBONDENSLAVE:
- case SIOCBONDRELEASE:
- case SIOCBONDSETHWADDR:
- case SIOCBONDSLAVEINFOQUERY:
- case SIOCBONDINFOQUERY:
- case SIOCBONDCHANGEACTIVE:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- dev_load(ifr.ifr_name);
- dev_probe_lock();
- rtnl_lock();
- ret = dev_ifsioc(&ifr, cmd);
- rtnl_unlock();
- dev_probe_unlock();
- return ret;
+ case SIOCSIFFLAGS:
+ case SIOCSIFMETRIC:
+ case SIOCSIFMTU:
+ case SIOCSIFMAP:
+ case SIOCSIFHWADDR:
+ case SIOCSIFSLAVE:
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ case SIOCSIFHWBROADCAST:
+ case SIOCSIFNAME:
+ case SIOCSMIIREG:
+ case SIOCBONDENSLAVE:
+ case SIOCBONDRELEASE:
+ case SIOCBONDSETHWADDR:
+ case SIOCBONDSLAVEINFOQUERY:
+ case SIOCBONDINFOQUERY:
+ case SIOCBONDCHANGEACTIVE:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ dev_load(ifr.ifr_name);
+ dev_probe_lock();
+ rtnl_lock();
+ ret = dev_ifsioc(&ifr, cmd);
+ rtnl_unlock();
+ dev_probe_unlock();
+ return ret;
- case SIOCGIFMEM:
- /* Get the per device memory space. We can add this but currently
- do not support it */
- case SIOCSIFMEM:
- /* Set the per device memory buffer space. Not applicable in our case */
- case SIOCSIFLINK:
- return -EINVAL;
-
- /*
- * Unknown or private ioctl.
- */
+ case SIOCGIFMEM:
+ /* Get the per device memory space. We can add this but currently
+ do not support it */
+ case SIOCSIFMEM:
+ /* Set the per device memory buffer space. */
+ case SIOCSIFLINK:
+ return -EINVAL;
+
+ /*
+ * Unknown or private ioctl.
+ */
- default:
- if (cmd >= SIOCDEVPRIVATE &&
- cmd <= SIOCDEVPRIVATE + 15) {
- dev_load(ifr.ifr_name);
- dev_probe_lock();
- rtnl_lock();
- ret = dev_ifsioc(&ifr, cmd);
- rtnl_unlock();
- dev_probe_unlock();
- if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq)))
- return -EFAULT;
- return ret;
- }
+ default:
+ if (cmd >= SIOCDEVPRIVATE &&
+ cmd <= SIOCDEVPRIVATE + 15) {
+ dev_load(ifr.ifr_name);
+ dev_probe_lock();
+ rtnl_lock();
+ ret = dev_ifsioc(&ifr, cmd);
+ rtnl_unlock();
+ dev_probe_unlock();
+ if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq)))
+ return -EFAULT;
+ return ret;
+ }
#ifdef WIRELESS_EXT
- /* Take care of Wireless Extensions */
- if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
+ /* Take care of Wireless Extensions */
+ if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
/* If command is `set a parameter', or
* `get the encoding parameters', check if
* the user has the right to do it */
- if (IW_IS_SET(cmd) || (cmd == SIOCGIWENCODE)) {
- if(!capable(CAP_NET_ADMIN))
- return -EPERM;
- }
- dev_load(ifr.ifr_name);
- rtnl_lock();
- ret = dev_ifsioc(&ifr, cmd);
- rtnl_unlock();
- if (!ret && IW_IS_GET(cmd) &&
- copy_to_user(arg, &ifr, sizeof(struct ifreq)))
- return -EFAULT;
- return ret;
- }
+ if (IW_IS_SET(cmd) || (cmd == SIOCGIWENCODE)) {
+ if(!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ }
+ dev_load(ifr.ifr_name);
+ rtnl_lock();
+ ret = dev_ifsioc(&ifr, cmd);
+ rtnl_unlock();
+ if (!ret && IW_IS_GET(cmd) &&
+ copy_to_user(arg, &ifr,
+ sizeof(struct ifreq)))
+ return -EFAULT;
+ return ret;
+ }
#endif /* WIRELESS_EXT */
- return -EINVAL;
- }
+ return -EINVAL;
+ }
}
int dev_new_index(void)
{
- static int ifindex;
- for (;;) {
- if (++ifindex <= 0)
- ifindex=1;
- if (__dev_get_by_index(ifindex) == NULL)
- return ifindex;
- }
+ static int ifindex;
+ for (;;) {
+ if (++ifindex <= 0)
+ ifindex=1;
+ if (__dev_get_by_index(ifindex) == NULL)
+ return ifindex;
+ }
}
static int dev_boot_phase = 1;
int register_netdevice(struct net_device *dev)
{
- struct net_device *d, **dp;
+ struct net_device *d, **dp;
#ifdef CONFIG_NET_DIVERT
- int ret;
+ int ret;
#endif
- spin_lock_init(&dev->queue_lock);
- spin_lock_init(&dev->xmit_lock);
- dev->xmit_lock_owner = -1;
+ spin_lock_init(&dev->queue_lock);
+ spin_lock_init(&dev->xmit_lock);
+ dev->xmit_lock_owner = -1;
#ifdef CONFIG_NET_FASTROUTE
- dev->fastpath_lock=RW_LOCK_UNLOCKED;
+ dev->fastpath_lock=RW_LOCK_UNLOCKED;
#endif
- if (dev_boot_phase)
- net_dev_init();
+ if (dev_boot_phase)
+ net_dev_init();
#ifdef CONFIG_NET_DIVERT
- ret = alloc_divert_blk(dev);
- if (ret)
- return ret;
+ ret = alloc_divert_blk(dev);
+ if (ret)
+ return ret;
#endif /* CONFIG_NET_DIVERT */
- dev->iflink = -1;
+ dev->iflink = -1;
- /* Init, if this function is available */
- if (dev->init && dev->init(dev) != 0) {
+ /* Init, if this function is available */
+ if (dev->init && dev->init(dev) != 0) {
#ifdef CONFIG_NET_DIVERT
- free_divert_blk(dev);
+ free_divert_blk(dev);
#endif
- return -EIO;
- }
+ return -EIO;
+ }
- dev->ifindex = dev_new_index();
- if (dev->iflink == -1)
- dev->iflink = dev->ifindex;
+ dev->ifindex = dev_new_index();
+ if (dev->iflink == -1)
+ dev->iflink = dev->ifindex;
- /* Check for existence, and append to tail of chain */
- for (dp=&dev_base; (d=*dp) != NULL; dp=&d->next) {
- if (d == dev || strcmp(d->name, dev->name) == 0) {
+ /* Check for existence, and append to tail of chain */
+ for (dp=&dev_base; (d=*dp) != NULL; dp=&d->next) {
+ if (d == dev || strcmp(d->name, dev->name) == 0) {
#ifdef CONFIG_NET_DIVERT
- free_divert_blk(dev);
+ free_divert_blk(dev);
#endif
- return -EEXIST;
- }
- }
- /*
- * nil rebuild_header routine,
- * that should be never called and used as just bug trap.
- */
-
- if (dev->rebuild_header == NULL)
- dev->rebuild_header = default_rebuild_header;
-
- /*
- * Default initial state at registry is that the
- * device is present.
- */
-
- set_bit(__LINK_STATE_PRESENT, &dev->state);
-
- dev->next = NULL;
- dev_init_scheduler(dev);
- write_lock_bh(&dev_base_lock);
- *dp = dev;
- dev_hold(dev);
- dev->deadbeaf = 0;
- write_unlock_bh(&dev_base_lock);
-
- /* Notify protocols, that a new device appeared. */
- notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
-
- return 0;
+ return -EEXIST;
+ }
+ }
+ /*
+ * nil rebuild_header routine,
+ * that should be never called and used as just bug trap.
+ */
+
+ if (dev->rebuild_header == NULL)
+ dev->rebuild_header = default_rebuild_header;
+
+ /*
+ * Default initial state at registry is that the
+ * device is present.
+ */
+
+ set_bit(__LINK_STATE_PRESENT, &dev->state);
+
+ dev->next = NULL;
+ dev_init_scheduler(dev);
+ write_lock_bh(&dev_base_lock);
+ *dp = dev;
+ dev_hold(dev);
+ dev->deadbeaf = 0;
+ write_unlock_bh(&dev_base_lock);
+
+ /* Notify protocols, that a new device appeared. */
+ notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
+
+ return 0;
}
/**
int netdev_finish_unregister(struct net_device *dev)
{
- BUG_TRAP(dev->ip_ptr==NULL);
- BUG_TRAP(dev->ip6_ptr==NULL);
- BUG_TRAP(dev->dn_ptr==NULL);
-
- if (!dev->deadbeaf) {
- printk(KERN_ERR "Freeing alive device %p, %s\n", dev, dev->name);
- return 0;
- }
+ BUG_TRAP(dev->ip_ptr==NULL);
+ BUG_TRAP(dev->ip6_ptr==NULL);
+ BUG_TRAP(dev->dn_ptr==NULL);
+
+ if (!dev->deadbeaf) {
+ printk(KERN_ERR "Freeing alive device %p, %s\n",
+ dev, dev->name);
+ return 0;
+ }
#ifdef NET_REFCNT_DEBUG
- printk(KERN_DEBUG "netdev_finish_unregister: %s%s.\n", dev->name,
- (dev->features & NETIF_F_DYNALLOC)?"":", old style");
+ printk(KERN_DEBUG "netdev_finish_unregister: %s%s.\n", dev->name,
+ (dev->features & NETIF_F_DYNALLOC)?"":", old style");
#endif
- if (dev->destructor)
- dev->destructor(dev);
- if (dev->features & NETIF_F_DYNALLOC)
- kfree(dev);
- return 0;
+ if (dev->destructor)
+ dev->destructor(dev);
+ if (dev->features & NETIF_F_DYNALLOC)
+ kfree(dev);
+ return 0;
}
/**
int unregister_netdevice(struct net_device *dev)
{
- unsigned long now, warning_time;
- struct net_device *d, **dp;
-
- /* If device is running, close it first. */
- if (dev->flags & IFF_UP)
- dev_close(dev);
-
- BUG_TRAP(dev->deadbeaf==0);
- dev->deadbeaf = 1;
-
- /* And unlink it from device chain. */
- for (dp = &dev_base; (d=*dp) != NULL; dp=&d->next) {
- if (d == dev) {
- write_lock_bh(&dev_base_lock);
- *dp = d->next;
- write_unlock_bh(&dev_base_lock);
- break;
- }
- }
- if (d == NULL) {
- printk(KERN_DEBUG "unregister_netdevice: device %s/%p never was registered\n", dev->name, dev);
- return -ENODEV;
- }
-
- /* Synchronize to net_rx_action. */
- br_write_lock_bh(BR_NETPROTO_LOCK);
- br_write_unlock_bh(BR_NETPROTO_LOCK);
-
- if (dev_boot_phase == 0) {
-
- /* Shutdown queueing discipline. */
- dev_shutdown(dev);
-
- /* Notify protocols, that we are about to destroy
- this device. They should clean all the things.
- */
- notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
-
- /*
- * Flush the multicast chain
- */
- dev_mc_discard(dev);
- }
-
- if (dev->uninit)
- dev->uninit(dev);
-
- /* Notifier chain MUST detach us from master device. */
- BUG_TRAP(dev->master==NULL);
+ unsigned long now, warning_time;
+ struct net_device *d, **dp;
+
+ /* If device is running, close it first. */
+ if (dev->flags & IFF_UP)
+ dev_close(dev);
+
+ BUG_TRAP(dev->deadbeaf==0);
+ dev->deadbeaf = 1;
+
+ /* And unlink it from device chain. */
+ for (dp = &dev_base; (d=*dp) != NULL; dp=&d->next) {
+ if (d == dev) {
+ write_lock_bh(&dev_base_lock);
+ *dp = d->next;
+ write_unlock_bh(&dev_base_lock);
+ break;
+ }
+ }
+ if (d == NULL) {
+ printk(KERN_DEBUG "unregister_netdevice: device %s/%p"
+ " not registered\n", dev->name, dev);
+ return -ENODEV;
+ }
+
+ /* Synchronize to net_rx_action. */
+ br_write_lock_bh(BR_NETPROTO_LOCK);
+ br_write_unlock_bh(BR_NETPROTO_LOCK);
+
+ if (dev_boot_phase == 0) {
+
+ /* Shutdown queueing discipline. */
+ dev_shutdown(dev);
+
+ /* Notify protocols, that we are about to destroy
+ this device. They should clean all the things.
+ */
+ notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
+
+ /*
+ * Flush the multicast chain
+ */
+ dev_mc_discard(dev);
+ }
+
+ if (dev->uninit)
+ dev->uninit(dev);
+
+ /* Notifier chain MUST detach us from master device. */
+ BUG_TRAP(dev->master==NULL);
#ifdef CONFIG_NET_DIVERT
- free_divert_blk(dev);
+ free_divert_blk(dev);
#endif
- if (dev->features & NETIF_F_DYNALLOC) {
+ if (dev->features & NETIF_F_DYNALLOC) {
#ifdef NET_REFCNT_DEBUG
- if (atomic_read(&dev->refcnt) != 1)
- printk(KERN_DEBUG "unregister_netdevice: holding %s refcnt=%d\n", dev->name, atomic_read(&dev->refcnt)-1);
+ if (atomic_read(&dev->refcnt) != 1)
+ printk(KERN_DEBUG "unregister_netdevice: holding %s refcnt=%d\n",
+ dev->name, atomic_read(&dev->refcnt)-1);
#endif
- dev_put(dev);
- return 0;
- }
+ dev_put(dev);
+ return 0;
+ }
- /* Last reference is our one */
- if (atomic_read(&dev->refcnt) == 1) {
- dev_put(dev);
- return 0;
- }
+ /* Last reference is our one */
+ if (atomic_read(&dev->refcnt) == 1) {
+ dev_put(dev);
+ return 0;
+ }
#ifdef NET_REFCNT_DEBUG
- printk("unregister_netdevice: waiting %s refcnt=%d\n", dev->name, atomic_read(&dev->refcnt));
+ printk("unregister_netdevice: waiting %s refcnt=%d\n",
+ dev->name, atomic_read(&dev->refcnt));
#endif
- /* EXPLANATION. If dev->refcnt is not now 1 (our own reference)
- it means that someone in the kernel still has a reference
- to this device and we cannot release it.
-
- "New style" devices have destructors, hence we can return from this
- function and destructor will do all the work later. As of kernel 2.4.0
- there are very few "New Style" devices.
-
- "Old style" devices expect that the device is free of any references
- upon exit from this function.
- We cannot return from this function until all such references have
- fallen away. This is because the caller of this function will probably
- immediately kfree(*dev) and then be unloaded via sys_delete_module.
-
- So, we linger until all references fall away. The duration of the
- linger is basically unbounded! It is driven by, for example, the
- current setting of sysctl_ipfrag_time.
-
- After 1 second, we start to rebroadcast unregister notifications
- in hope that careless clients will release the device.
-
- */
-
- now = warning_time = jiffies;
- while (atomic_read(&dev->refcnt) != 1) {
- if ((jiffies - now) > 1*HZ) {
- /* Rebroadcast unregister notification */
- notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
- }
- mdelay(250);
- if ((jiffies - warning_time) > 10*HZ) {
- printk(KERN_EMERG "unregister_netdevice: waiting for %s to "
- "become free. Usage count = %d\n",
- dev->name, atomic_read(&dev->refcnt));
- warning_time = jiffies;
- }
- }
- dev_put(dev);
- return 0;
+ /* EXPLANATION. If dev->refcnt is not now 1 (our own reference)
+ it means that someone in the kernel still has a reference
+ to this device and we cannot release it.
+
+ "New style" devices have destructors, hence we can return from this
+ function and destructor will do all the work later. As of kernel 2.4.0
+ there are very few "New Style" devices.
+
+ "Old style" devices expect that the device is free of any references
+ upon exit from this function.
+ We cannot return from this function until all such references have
+ fallen away. This is because the caller of this function will probably
+ immediately kfree(*dev) and then be unloaded via sys_delete_module.
+
+ So, we linger until all references fall away. The duration of the
+ linger is basically unbounded! It is driven by, for example, the
+ current setting of sysctl_ipfrag_time.
+
+ After 1 second, we start to rebroadcast unregister notifications
+ in hope that careless clients will release the device.
+
+ */
+
+ now = warning_time = jiffies;
+ while (atomic_read(&dev->refcnt) != 1) {
+ if ((jiffies - now) > 1*HZ) {
+ /* Rebroadcast unregister notification */
+ notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
+ }
+ mdelay(250);
+ if ((jiffies - warning_time) > 10*HZ) {
+ printk(KERN_EMERG "unregister_netdevice: waiting for %s to "
+ "become free. Usage count = %d\n",
+ dev->name, atomic_read(&dev->refcnt));
+ warning_time = jiffies;
+ }
+ }
+ dev_put(dev);
+ return 0;
}
*/
int __init net_dev_init(void)
{
- struct net_device *dev, **dp;
- int i;
+ struct net_device *dev, **dp;
+ int i;
- if (!dev_boot_phase)
- return 0;
+ if ( !dev_boot_phase )
+ return 0;
+
+ /* KAF: was sone in socket_init, but that top-half stuff is gone. */
+ skb_init();
+
+ /* Initialise the packet receive queues. */
+ for ( i = 0; i < NR_CPUS; i++ )
+ {
+ struct softnet_data *queue;
+ queue = &softnet_data[i];
+ queue->completion_queue = NULL;
+ }
+
+ /*
+ * Add the devices.
+ * If the call to dev->init fails, the dev is removed
+ * from the chain disconnecting the device until the
+ * next reboot.
+ *
+ * NB At boot phase networking is dead. No locking is required.
+ * But we still preserve dev_base_lock for sanity.
+ */
+ dp = &dev_base;
+ while ((dev = *dp) != NULL) {
+ spin_lock_init(&dev->queue_lock);
+ spin_lock_init(&dev->xmit_lock);
+
+ dev->xmit_lock_owner = -1;
+ dev->iflink = -1;
+ dev_hold(dev);
/*
- * KAF: was sone in socket_init, but that top-half stuff is gone.
+ * Allocate name. If the init() fails
+ * the name will be reissued correctly.
*/
- skb_init();
-
- /*
- * Initialise the packet receive queues.
- */
-
- for (i = 0; i < NR_CPUS; i++) {
- struct softnet_data *queue;
-
- queue = &softnet_data[i];
- skb_queue_head_init(&queue->input_pkt_queue);
- queue->throttle = 0;
- queue->cng_level = 0;
- queue->avg_blog = 10; /* arbitrary non-zero */
- queue->completion_queue = NULL;
- }
-
- /*
- * Add the devices.
- * If the call to dev->init fails, the dev is removed
- * from the chain disconnecting the device until the
- * next reboot.
- *
- * NB At boot phase networking is dead. No locking is required.
- * But we still preserve dev_base_lock for sanity.
- */
-
- dp = &dev_base;
- while ((dev = *dp) != NULL) {
- spin_lock_init(&dev->queue_lock);
- spin_lock_init(&dev->xmit_lock);
-
- dev->xmit_lock_owner = -1;
- dev->iflink = -1;
- dev_hold(dev);
-
- /*
- * Allocate name. If the init() fails
- * the name will be reissued correctly.
- */
- if (strchr(dev->name, '%'))
- dev_alloc_name(dev, dev->name);
-
- if (dev->init && dev->init(dev)) {
- /*
- * It failed to come up. It will be unhooked later.
- * dev_alloc_name can now advance to next suitable
- * name that is checked next.
- */
- dev->deadbeaf = 1;
- dp = &dev->next;
- } else {
- dp = &dev->next;
- dev->ifindex = dev_new_index();
- if (dev->iflink == -1)
- dev->iflink = dev->ifindex;
- if (dev->rebuild_header == NULL)
- dev->rebuild_header = default_rebuild_header;
- dev_init_scheduler(dev);
- set_bit(__LINK_STATE_PRESENT, &dev->state);
- }
- }
-
- /*
- * Unhook devices that failed to come up
- */
- dp = &dev_base;
- while ((dev = *dp) != NULL) {
- if (dev->deadbeaf) {
- write_lock_bh(&dev_base_lock);
- *dp = dev->next;
- write_unlock_bh(&dev_base_lock);
- dev_put(dev);
- } else {
- dp = &dev->next;
- }
- }
-
- dev_boot_phase = 0;
-
- open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
- //open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL);
-
- dst_init();
- dev_mcast_init();
+ if (strchr(dev->name, '%'))
+ dev_alloc_name(dev, dev->name);
+
+ if (dev->init && dev->init(dev)) {
+ /*
+ * It failed to come up. It will be unhooked later.
+ * dev_alloc_name can now advance to next suitable
+ * name that is checked next.
+ */
+ dev->deadbeaf = 1;
+ dp = &dev->next;
+ } else {
+ dp = &dev->next;
+ dev->ifindex = dev_new_index();
+ if (dev->iflink == -1)
+ dev->iflink = dev->ifindex;
+ if (dev->rebuild_header == NULL)
+ dev->rebuild_header = default_rebuild_header;
+ dev_init_scheduler(dev);
+ set_bit(__LINK_STATE_PRESENT, &dev->state);
+ }
+ }
+
+ /*
+ * Unhook devices that failed to come up
+ */
+ dp = &dev_base;
+ while ((dev = *dp) != NULL) {
+ if (dev->deadbeaf) {
+ write_lock_bh(&dev_base_lock);
+ *dp = dev->next;
+ write_unlock_bh(&dev_base_lock);
+ dev_put(dev);
+ } else {
+ dp = &dev->next;
+ }
+ }
+
+ dev_boot_phase = 0;
+
+ dst_init();
+ dev_mcast_init();
#ifdef CONFIG_NET_SCHED
- pktsched_init();
+ pktsched_init();
#endif
- /*
- * Initialise network devices
- */
+ /*
+ * Initialise network devices
+ */
- net_device_init();
+ net_device_init();
- return 0;
+ return 0;
}
inline int init_tx_header(u8 *data, unsigned int len, struct net_device *dev)
{
- memcpy(data + ETH_ALEN, dev->dev_addr, ETH_ALEN);
+ memcpy(data + ETH_ALEN, dev->dev_addr, ETH_ALEN);
- switch ( ntohs(*(unsigned short *)(data + 12)) )
- {
- case ETH_P_ARP:
- if ( len < 42 ) break;
- memcpy(data + 22, dev->dev_addr, 6);
- return ETH_P_ARP;
- case ETH_P_IP:
- return ETH_P_IP;
- }
- return 0;
+ switch ( ntohs(*(unsigned short *)(data + 12)) )
+ {
+ case ETH_P_ARP:
+ if ( len < 42 ) break;
+ memcpy(data + 22, dev->dev_addr, 6);
+ return ETH_P_ARP;
+ case ETH_P_IP:
+ return ETH_P_IP;
+ }
+ return 0;
}